hdu 1540 Tunnel Warfare
题目描述:给定连续的n个村庄,有三种操作:
1.D x:毁掉第x个村庄;
2.Q x:询问直接或间接与x相连的村庄数目
3.R :恢复上一个被毁掉的村庄。
分析:用线段树维护区间内以左端点开始的连续区间,以右端点结束的连续区间。
询问我拆成了两部分,一个是询问x向右(含x)的连续区间长,一个是询问x向左(含x)的连续区间长,加和减一就是答案。
操作三用个栈记录下就行。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define N 50010 6 #define lson l,m,n<<1 7 #define rson m+1,r,n<<1|1 8 using namespace std; 9 int s[N<<2][2]; 10 int x[N]; 11 int stack[N]; 12 void pushup(int n,int m){ 13 s[n][0]=s[n<<1][0]; 14 if(s[n][0]==(m-(m>>1)))s[n][0]+=s[n<<1|1][0]; 15 s[n][1]=s[n<<1|1][1]; 16 if(s[n][1]==(m>>1))s[n][1]+=s[n<<1][1]; 17 } 18 void build(int l,int r,int n){ 19 s[n][0]=s[n][1]=r-l+1; 20 if(l==r)return; 21 int m=(l+r)>>1; 22 build(lson); 23 build(rson); 24 } 25 void update(int nn,int f,int l,int r,int n){ 26 if(l==r){ 27 s[n][0]=s[n][1]=f; 28 return; 29 } 30 int m=(l+r)>>1; 31 if(nn<=m)update(nn,f,lson); 32 else update(nn,f,rson); 33 pushup(n,r-l+1); 34 } 35 int queryl(int nn,int l,int r,int n){ 36 if(l+s[n][0]-1>=nn)return l+s[n][0]-nn; 37 int m=(l+r)>>1; 38 if(nn<=m){ 39 int a=queryl(nn,lson); 40 if(a==(m-nn+1))a+=s[n<<1|1][0]; 41 return a; 42 } 43 else 44 return queryl(nn,rson); 45 } 46 int queryr(int nn,int l,int r,int n){ 47 if(r-s[n][1]+1<=nn)return nn-r+s[n][1]; 48 else{ 49 int m=(l+r)>>1; 50 if(nn<=m)return queryr(nn,lson); 51 else{ 52 int a=queryr(nn,rson); 53 if(a==(nn-m))a+=s[n<<1][1]; 54 return a; 55 } 56 } 57 } 58 int main(){ 59 int n,m; 60 while(~scanf("%d%d",&n,&m)){ 61 build(1,n,1); 62 memset(x,1,sizeof(x)); 63 char op[5]; 64 int a,top=0; 65 while(m--){ 66 scanf("%s",op); 67 if(op[0]=='D'){ 68 scanf("%d",&a); 69 update(a,0,1,n,1); 70 stack[++top]=a; 71 x[a]=0; 72 }else if(op[0]=='Q'){ 73 scanf("%d",&a); 74 if(x[a]==0)puts("0"); 75 else 76 printf("%d\n",queryl(a,1,n,1)+queryr(a,1,n,1)-1); 77 }else{ 78 update(stack[top],1,1,n,1); 79 x[stack[top]]=1; 80 --top; 81 } 82 } 83 } 84 return 0; 85 }