转化为平面上的坐标(x,y),set维护连续区间.
用树套树维护矩阵加法,单点查询。
注意维护矩阵差分的时候,
$(x,y,v)$是对$(x,y)(n+1,n+1)$的矩阵做出贡献
#include<iostream> #include<cstdio> #include<cstring> #include<set> #define ri register int using namespace std; int read(){ char c=getchar(); ri x=0; while(c<'0'||c>'9') c=getchar(); while('0'<=c&&c<='9') x=x*10+c-48,c=getchar(); return x; } #define N 600005 #define W 20000005 struct E{ int l,r; E(int A,int B):l(A),r(B){} bool operator < (const E &G) const{return r<G.r;} };set<E> g; set<E>::iterator it; int n,T,a[N]; char opt[9],cc[N]; int cnt,rt[N],lc[W],rc[W],s[W]; #define mid (l+r)/2 void Ins1(int &o,int l,int r,int x,int v){ if(!o)o=++cnt; s[o]+=v; if(l==r) return; if(x<=mid) Ins1(lc[o],l,mid,x,v); else Ins1(rc[o],mid+1,r,x,v); } int Ask1(int o,int l,int r,int x1,int x2){ if(!o||x2<l||r<x1) return 0; if(x1<=l&&r<=x2) return s[o]; return Ask1(lc[o],l,mid,x1,x2)+Ask1(rc[o],mid+1,r,x1,x2); } void Ins2(int x,int y,int v){for(;x<=n+1;x+=x&-x)Ins1(rt[x],1,n+1,y,v);} int Ask2(int x,int y){int re=0; for(;x;x-=x&-x)re+=Ask1(rt[x],1,n+1,1,y); return re;} inline void Add(int x1,int y1,int x2,int y2,int v){//注意修改标记是对右上的查询产生贡献,并不是平移区间 Ins2(x1,y1,v),Ins2(x1,y2+1,-v),Ins2(x2+1,y1,-v),Ins2(x2+1,y2+1,v); } int main(){ n=read()+1; T=read(); scanf("%s",cc+1); for(ri i=1;i<=n;++i) g.insert(E(i,i)); int x,y,pl,pr,ql,qr; for(ri i=1;i<n;++i) if((a[i]=cc[i]-48)){ it=g.lower_bound(E(0,i+1)); --it; pl=(*it).l; g.erase(it); g.erase(E(i+1,i+1)); g.insert(E(pl,i+1)); } for(it=g.begin();it!=g.end();++it) Add((*it).l,(*it).l,(*it).r,(*it).r,T); for(ri t=1;t<=T;++t){ scanf("%s",opt); if(opt[0]=='q'){ x=read(); y=read(); pl=(*(g.lower_bound(E(0,x)))).l; ql=(*(g.lower_bound(E(0,y)))).l; printf("%d ",Ask2(x,y)-(T-t)*(pl==ql)); }else{ x=read(); if(a[x]){ it=g.lower_bound(E(0,x)); pl=(*it).l,pr=x; ql=x+1,qr=(*it).r; Add(pl,ql,pr,qr,t-T); g.erase(it); g.insert(E(pl,pr)); g.insert(E(ql,qr)); }else{ it=g.lower_bound(E(0,x)); pl=(*it).l,pr=x; ++it; ql=x+1,qr=(*it).r; Add(pl,ql,pr,qr,T-t); g.erase(E(pl,pr)); g.erase(E(ql,qr)); g.insert(E(pl,qr)); }a[x]^=1; } }return 0; }