F. SUM and REPLACE(线段树&dsu)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了F. SUM and REPLACE(线段树&dsu)相关的知识,希望对你有一定的参考价值。
F. SUM and REPLACE(线段树&dsu)
与区间开平方是一个题型,区间变成 d ( i ) d(i) d(i) 最多变 6 6 6次。
可以线段树维护区间和和区间最大值,当区间最大值 ≤ 2 \\le 2 ≤2直接返回不修改。
然后就是裸的线段树。
线段树代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,i,j,k,t[1200005],a[300005],d[1000005];
ll s[1200005];
void up(int R)
{
s[R]=s[R<<1]+s[R<<1|1];
t[R]=max(t[R<<1],t[R<<1|1]);
}
void build(int R,int l,int r)
{
if(l==r)
{
s[R]=t[R]=a[l];
return;
}
int mid=l+r>>1;
build(R<<1,l,mid);
build(R<<1|1,mid+1,r);
up(R);
}
ll ask(int R,int l,int r,int l1,int r1)
{
if(l1<=l&&r<=r1)return s[R];
int mid=l+r>>1;
ll s=0;
if(l1<=mid)s+=ask(R<<1,l,mid,l1,r1);
if(r1>mid)s+=ask(R<<1|1,mid+1,r,l1,r1);
return s;
}
void fix(int R,int l,int r,int l1,int r1)
{
if(t[R]<3)return;
if(l==r)
{
s[R]=t[R]=d[t[R]];
return;
}
int mid=l+r>>1;
if(l1<=mid)fix(R<<1,l,mid,l1,r1);
if(r1>mid)fix(R<<1|1,mid+1,r,l1,r1);
up(R);
}
int main()
{
for(i=1;i<=1000000;i++)for(j=i;j<=1000000;j+=i)d[j]++;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",a+i);
build(1,1,n);
while(m--)
{
scanf("%d%d%d",&i,&j,&k);
if(i==1)fix(1,1,n,j,k);
else cout<<ask(1,1,n,j,k)<<endl;
}
return 0;
}
此题还有个解法:利用并查集,每个结点向右连第一个大于 d ( i ) > 2 d(i)>2 d(i)>2的位置。
每次就一边更新区间,一遍修改 d s u dsu dsu即可,直接区间求和,上线段树或者BIT都可。
d s u dsu dsu代码
#include<cstdio>
const int N=1000006;
int n,m,i,j,k,a[N],d[N],f[N],opt,l,r;
long long c[N],s;
int p(int x){
return x==f[x]?x:f[x]=p(f[x]);
}
void add(int x,int y){
while(y<=n)
c[y]+=x,y+=y&-y;
}
long long sum(int x){
for(s=0;x;x-=x&-x)
s+=c[x];
return s;
}
int main(){
for(i=1;i<N;i++)
for(j=i;j<N;j+=i)
d[j]++;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",a+i);
add(a[i],i);
if(a[i]>2)
f[i]=i;
else
f[i]=i+1;
}
f[i]=i;
while(m--){
scanf("%d%d%d",&opt,&l,&r);
if(opt==1){
while((l=p(l))<=r){
add(-a[l],l);
a[l]=d[a[l]];
add(a[l],l);
if(a[l]<=2)
f[l]=l+1;
l++;
}
}
else
printf("%lld\\n",sum(r)-sum(l-1));
}
}
以上是关于F. SUM and REPLACE(线段树&dsu)的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces - 920F SUM and REPLACE (线段树)
codeforces CF920F SUM and REPLACE 线段树 线性筛约数
Educational Codeforces Round 37-F.SUM and REPLACE (线段树,线性筛,收敛函数)
Educational Codeforces Round 37F. SUM and REPLACE 线段树+线性筛
Codeforces Round #638 (Div. 2) F. Phoenix and Memory 区间贪心+线段树