CF671C Ultimate Weirdness of an Array 数论线段树
Posted itst
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF671C Ultimate Weirdness of an Array 数论线段树相关的知识,希望对你有一定的参考价值。
考虑计算(forall p in [0,200000] , sumlimits_{l} sumlimits_{r geq l} [f_{l,r} leq p]),这样我们通过差分可以得到最后的答案。
首先不难发现当固定了某个左端点(l)和(p)之后,满足条件的(r)一定是原序列的一段后缀。设(r_l)表示当左端点为(l)时最小的右端点,那么(l)作为左端点对答案的贡献就是(N+1-r_l)。
考虑当(p)变为(p-1)时(r_x)会如何变化。这相当于去掉满足(f_{l,r} = p)的区间,而这又等价于不能让当前区间之外的部分出现至少(2)个(p)的倍数。
把所有(p)的倍数拿出来形成一个序列(x_1,x_2,...,x_k),如果(k leq 1)显然不会做操作,否则区间([l,r])内至少要包含序列中的至少(k-1)个位置。也就是说:
1、当(l > x_2)时,(r_l = N + 1),这表示已经不存在区间满足条件了;
2、当(l in (x_1,x_2])时,(r_l = max{r_l , x_m}),也就是至少要把(x_2 sim x_m)覆盖;
3、当(l in [1,x_1])时,(r_l = max{r_l , x_{m-1}}),也就是至少要把(x_1 sim x_{m-1})覆盖。
所以我们需要一个数据结构支持区间(max)和区间和。似乎要写jiry树,但是因为(r_l)一定是单调不降的,所以在给定覆盖区间和取(max)的值之后被修改的区间一定是一段前缀,于是这个操作就等价于区间赋值了。这个就可以比较优美地实现。
#include<bits/stdc++.h>
using namespace std;
int read(){
int a = 0; char c = getchar();
while(!isdigit(c)) c = getchar();
while(isdigit(c)){a = a * 10 + c - 48; c = getchar();}
return a;
}
#define int long long
const int _ = 2e5 + 7 , M = 2e5;
namespace segt{
int sum[_ << 2] , mrk[_ << 2] , mx[_ << 2] , mn[_ << 2] , sz[_ << 2];
#define mid ((l + r) >> 1)
#define lch (x << 1)
#define rch (x << 1 | 1)
void mark(int x , int val){mrk[x] = mx[x] = mn[x] = val; sum[x] = sz[x] * val;}
void down(int x){if(mrk[x]){mark(lch , mrk[x]); mark(rch , mrk[x]); mrk[x] = 0;}}
void up(int x){sum[x] = sum[lch] + sum[rch]; mx[x] = mx[rch]; mn[x] = mn[lch];}
void init(int x , int l , int r){
sz[x] = r - l + 1;
if(l == r) sum[x] = mx[x] = mn[x] = l; else{init(lch , l , mid); init(rch , mid + 1 , r); up(x);}
}
void mdy(int x , int l , int r , int L , int R , int val){
if(L > R || mn[x] >= val) return;
if(l >= L && r <= R && mx[x] <= val) return mark(x , val);
down(x);
if(mid >= L) mdy(lch , l , mid , L , R , val);
if(mid < R) mdy(rch , mid + 1 , r , L , R , val);
up(x);
}
}using namespace segt;
int N , arr[_] , ans[_]; vector < int > ys[_] , pos[_];
signed main() {
N = read();
for(int i = 1 ; i <= M ; ++i)
for(int j = 1 ; j * i <= M ; ++j)
ys[i * j].emplace_back(i);
for(int i = 1 ; i <= N ; ++i){int id = read(); for(auto t : ys[id]) pos[t].emplace_back(i);}
init(1 , 1 , N); ans[M] = (N + 1) * N - sum[1];
for(int i = M ; i ; --i){
if(pos[i].size() > 1){
mdy(1 , 1 , N , pos[i][1] + 1 , N , N + 1);
mdy(1 , 1 , N , pos[i][0] + 1 , pos[i][1] , pos[i][pos[i].size() - 1]);
mdy(1 , 1 , N , 1 , pos[i][0] , pos[i][pos[i].size() - 2]);
}
ans[i - 1] = (N + 1) * N - sum[1];
}
int sum = 0; for(int i = 1 ; i <= M ; ++i) sum += (ans[i] - ans[i - 1]) * i;
cout << sum; return 0;
}
以上是关于CF671C Ultimate Weirdness of an Array 数论线段树的主要内容,如果未能解决你的问题,请参考以下文章
IntelliJ IDEA(Ultimate版本)的下载安装和WordCount的初步使用(本地模式和集群模式)Ultimate
请问WIN7的professional和ultimate不同
Windows 7 版本里面的Ultimate,Professional,Home Premium
Visual Studio ultimate 2012 RC的评估期将在3天后结束,您将需要升级到最新版本?? 必须升级吗?