Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3293 Accepted Submission(s): 1272
1)多case (2)某个村庄可以被毁坏多次(必须全部入栈),但只需要一次就能将其恢复(下面的这组数据,,) (3)D 3 D 2 D 1 D 1 D 2 R 恢复2 R 恢复1 R 恢复3其实根本不用。这么做反而wa了。不用考虑那么多D就直接入栈。R就直接出栈就行了。
#include <iostream> #include<stdio.h> #include<string.h> using namespace std; const int maxn=50010; int ml[maxn<<2],mr[maxn<<2],sta[maxn];//sta为栈 int flag,tail; void btree(int L,int R,int k) { int ls,rs,mid; ml[k]=mr[k]=R-L+1; if(L==R) return; ls=k<<1; rs=ls|1; mid=(L+R)>>1; btree(L,mid,ls); btree(mid+1,R,rs); } void update(int L,int R,int k,int p,int op)//更新很简单 { int ls,rs,mid; if(L==R) { if(op) ml[k]=mr[k]=0; else ml[k]=mr[k]=1; return; } ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(p>mid) update(mid+1,R,rs,p,op); else update(L,mid,ls,p,op); ml[k]=ml[ls]; mr[k]=mr[rs]; if(ml[ls]==mid-L+1) ml[k]+=ml[rs]; if(mr[rs]==R-mid) mr[k]+=mr[ls]; } int qu(int L,int R,int k,int p) { int ls,rs,mid,t; if(mr[k]>=R-p+1) { flag=1;//加以标记。返回上层时加上扩展值 return mr[k]; } if(ml[k]>=p-L+1) { flag=1; return ml[k]; } if(L==R) return 0; ls=k<<1; rs=ls|1; mid=(L+R)>>1; if(p>mid) { t=qu(mid+1,R,rs,p); if(flag) { flag=0; t+=mr[ls]; } } else { t=qu(L,mid,ls,p); if(flag) { flag=0; t+=ml[rs]; } } return t; } int main() { int n,m,p,i; char com[10]; while(~scanf("%d%d",&n,&m)) { btree(1,n,1); flag=tail=0; for(i=0;i<m;i++) { scanf("%s",com); switch(com[0]) { case 'D': scanf("%d",&p); update(1,n,1,p,1); sta[tail++]=p; break; case 'Q': scanf("%d",&p); flag=0;//注意flag初始化! printf("%d\n",qu(1,n,1,p)); break; case 'R': update(1,n,1,sta[--tail],0); } } } return 0; } /* 3 100 D 3 D 1 D 2 R Q 1 Q 2 Q 3 R Q 1 Q 2 Q 3 */