题意:给你一个完整的1~n区间,他们是连续的,D代表破坏某个村庄,Q代表询问这个村庄何其他几何村庄相连,R代表修复村庄
思路:并不会用线段树维护区间,之前卡了好久,直到自己把样例画出来(还是太懒了),这才明白线段树维护区间的意思,,然后参照大牛的博客才水过
代码:
#include <bits/stdc++.h> using namespace std; const int INF=0x3f3f3f3f; const int maxn=50000+10; int lsum[maxn<<2],rsum[maxn<<2]; int s[maxn],top,n,m,a; char ch[2]; bool mark[maxn]; void pushdown(int i,int len) { lsum[i]=lsum[i<<1]; rsum[i]=rsum[i<<1|1]; if(lsum[i]==len-(len>>1))lsum[i]+=lsum[i<<1|1]; if(rsum[i]==(len>>1))rsum[i]+=rsum[i<<1]; } void build(int l,int r,int i) { lsum[i]=rsum[i]=r-l+1; if(l==r)return ; int mid=(l+r)>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); } void update(int p,int date,int l,int r,int i) { if(l==r){ rsum[i]+=date; lsum[i]=rsum[i]; return ; } int mid=(l+r)>>1; if(p<=mid)update(p,date,l,mid,i<<1); else update(p,date,mid+1,r,i<<1|1); pushdown(i,r-l+1); } int queryL(int L,int R,int l,int r,int i) { if(L<=l&&r<=R){ return lsum[i]; } int mid=(l+r)>>1; if(R<=mid)queryL(L,R,l,mid,i<<1); else if(mid<L)queryL(L,R,mid+1,r,i<<1|1); else{ int lans=queryL(L,mid,l,mid,i<<1); int rans=queryL(mid+1,R,mid+1,r,i<<1|1); if(lans==mid-L+1)return lans+rans; return lans; } } int queryR(int L,int R,int l,int r,int i) { if(L<=l&&r<=R){ return rsum[i]; } int mid=(l+r)>>1; if(R<=mid)queryR(L,R,l,mid,i<<1); else if(mid<L)queryR(L,R,mid+1,r,i<<1|1); else{ int lans=queryR(L,mid,l,mid,i<<1); int rans=queryR(mid+1,R,mid+1,r,i<<1|1); if(rans==R-mid)return lans+rans; return rans; } } int main() { while(~scanf("%d%d",&n,&m)){ build(1,n,1); memset(mark,false,sizeof(mark)); mark[0]=true,top=0; for(int i=0;i<m;i++){ scanf("%s",ch); if(ch[0]=='D'){ scanf("%d",&a); s[++top]=a; if(!mark[a])update(a,-1,1,n,1),mark[a]=true; } else if(ch[0]=='R'){ while(!mark[s[top]])--top; if(top)update(s[top],1,1,n,1),mark[s[top--]]=false; } else{ scanf("%d",&a); int temp=queryL(a,n,1,n,1)+queryR(1,a,1,n,1); printf("%d ",temp>0?temp-1:0); } } } return 0; }