带修改莫队——BZOJ2120/Luogu1903 数颜色

来源:互联网 发布:电脑网络npc怎么设置 编辑:程序博客网 时间:2024/06/05 04:10

题面:BZOJ2120
洛谷上呢这题作为带修改莫队的模板题:Luogu1903
所以这题做法就是带修改莫队算法辣
如何在原来的离线莫队上面加上修改操作呢?
我们可以多维护一个时间,当区间做到某个询问时,把询问前面的修改全部加上,把后面的修改全部还原,这样就可以兹瓷修改操作了
具体实现呢和原来移动区间差不多,也是移动时间轴
然后排序的方法是三关键字:左端点处在的块 -> 右端点 -> 时间

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>#include<cstdlib>#include<ctime>#include<string>#include<queue>#include<climits>using namespace std;struct ppap{int l,r,k,t,x;}a[100001];struct xg{int x,y,la;}b[100001];int o[1000001],v[100001],n,m,A=0,B=0;int ans[100001],la[100001],sum=0,l,r,t;inline bool cmp(ppap a,ppap b){    if(a.k!=b.k)return a.k<b.k;    if(a.r!=b.r)return a.r<b.r;    return a.t<b.t;}inline void xg(int x,int y){    if(x>=l&&x<=r){        o[v[x]]--;if(!o[v[x]])sum--;        v[x]=y;if(!o[y])sum++;o[y]++;    }else v[x]=y;}inline void gx(int x,int y){    int p=o[v[x]];o[v[x]]+=y;    if(!p&&o[v[x]])sum++;if(p&&!o[v[x]])sum--;}inline void work(){    l=1,r=0,t=0;    for(int i=1;i<=A;i++){        while(t>a[i].t)xg(b[t].x,b[t].la),t--;        while(t<a[i].t)t++,xg(b[t].x,b[t].y);        while(r<a[i].r)r++,gx(r,1);        while(l>a[i].l)l--,gx(l,1);        while(r>a[i].r)gx(r,-1),r--;        while(l<a[i].l)gx(l,-1),l++;        ans[a[i].x]=sum;    }}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)scanf("%d",&v[i]),la[i]=v[i];    int p=sqrt(n);    for(int i=1;i<=m;i++){        char c[5];int x,y;scanf("%s%d%d",c+1,&x,&y);        if(c[1]=='Q'){            a[++A].l=x;a[A].r=y;a[A].x=A;a[A].t=B;a[A].k=(n-1)/p+1;        }else{            b[++B].x=x;b[B].y=y;b[B].la=la[x];la[x]=y;        }    }    sort(a+1,a+A+1,cmp);    work();    for(int i=1;i<=A;i++)printf("%d\n",ans[i]);    return 0;}
原创粉丝点击