bzoj 2120: 數顏色【帶修改莫隊】
阿新 • • 發佈:2018-09-27
ons getc truct string 記錄 bool main space int
比較裸的帶修莫隊,對每個修改操作記一下它修改的位置修改前的顏色
然後正常莫隊,每次對修改操作時間倒流一下即可
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=200005; int n,m,bl[N],la[N],co[1000005],ta,tb,v[N],con[1000005],ans[N],nw; char s[10]; struct qw { int p,c,pr; }a[N]; struct qwe { int l,r,id,ti; }b[N]; bool cmp(const qwe &a,const qwe &b) { return bl[a.l]<bl[b.l]||(bl[a.l]==bl[b.l]&&a.r<b.r); } int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } void clc(int x) { if(v[x]) { if(!--con[co[x]]) nw--; } else if(++con[co[x]]==1) nw++; v[x]^=1; } void change(int x,int c) { if(v[x]) { clc(x); co[x]=c; clc(x); } else co[x]=c; } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) la[i]=co[i]=read(); for(int i=1;i<=m;i++) { scanf("%s",s); int x=read(),y=read(); if(s[0]==‘R‘) { a[++ta].p=x; a[ta].c=y; a[ta].pr=la[x];//記錄更改之前的顏色 la[x]=y; } else { b[++tb].l=x; b[tb].r=y; b[tb].id=tb; b[tb].ti=ta;//記錄他之前的離他最近的操作 } } int kuai=sqrt(n); for(int i=1;i<=n;i++) bl[i]=(i-1)/kuai+1; sort(b+1,b+tb+1,cmp); int l=1,r=1; clc(l); for(int i=1;i<=tb;i++) { for(int j=b[i-1].ti+1;j<=b[i].ti;j++) change(a[j].p,a[j].c); for(int j=b[i-1].ti;j>b[i].ti;j--) change(a[j].p,a[j].pr); while(l<b[i].l) clc(l++); while(l>b[i].l) clc(--l); while(r<b[i].r) clc(++r); while(r>b[i].r) clc(r--); ans[b[i].id]=nw; } for(int i=1;i<=tb;i++) printf("%d\n",ans[i]); return 0; }
bzoj 2120: 數顏色【帶修改莫隊】