/* * File: main.cpp * Author: Mi *其实这个题得解法和3667的很相似,用lv,rv分别保存左边连续的个数和右边连续的个数 * 在询问的时候有一点要注意,if(x<=mid) 则要去判断x是不是在T[root<<1].rv中,其实判断的方式就是 * if(x>T[root<<1].r-T[root<<1].rv) 那么就可以说明x在rv中,return T[root<<1].rv+T[root<<1|1].lv因为这样的话 * 就会与右子树的lv相接触所以还要加上T[root<<1|1].lv 判断在不在左子树的lv中的方法类似 * 在更新的时候没什么好说的和3667的方式一样,如果不懂可以看我写的,写得很详细: * http://blog.csdn.net/Euler_M/archive/2011/03/14/6248736.aspx * 线段树博大精深,要学好用好 * Created on 2011年3月14日, 下午7:15 */ #include <cstdlib> #include <stdio.h> #include <string.h> #include <stack> #define N 50005 using namespace std; /* * */ struct tree { int l,r,rv,lv,state; }T[N*3]; void build(int l,int r,int root) { T[root].l=l,T[root].r=r; if(l==r) { T[root].state=0; T[root].lv=T[root].rv=1; return ; } int mid=(l+r)>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); T[root].lv=T[root].rv=T[root].r-T[root].l+1; } void modify(int x,int root,int d) { if(T[root].l==T[root].r) { T[root].state=d; if(d) T[root].lv=T[root].rv=0; else T[root].lv=T[root].rv=1; return ; } int mid=(T[root].l+T[root].r)>>1; if(x<=mid) modify(x,root<<1,d); else modify(x,root<<1|1,d); T[root].lv=T[root<<1].lv; T[root].rv=T[root<<1|1].rv; if(T[root].lv==T[root<<1].r-T[root<<1].l+1) T[root].lv+=T[root<<1|1].lv; if(T[root].rv==T[root<<1|1].r-T[root<<1|1].l+1) T[root].rv+=T[root<<1].rv; } int query(int x,int root) { if(T[root].r==T[root].l) return (T[root].state==0?1:0); int mid=(T[root].l+T[root].r)>>1; if(x<=mid) { if(x>T[root<<1].r-T[root<<1].rv) return T[root<<1].rv+T[root<<1|1].lv; else query(x,root<<1); } else { if(x<T[root<<1|1].l+T[root<<1|1].lv) return T[root<<1].rv+T[root<<1|1].lv; else query(x,root<<1|1); } } int main(int argc, char** argv) { int n,q; stack<int> p; scanf("%d%d",&n,&q); build(1,n,1); while(!p.empty()) p.pop(); while(q--) { int temp,a; char s[2]; scanf("%s",s); if(s[0]=='D') { scanf("%d",&a); p.push(a); modify(a,1,1); } else if(s[0]=='Q') { scanf("%d",&a); temp=query(a,1); printf("%d/n",temp); } else { temp=p.top(); p.pop(); modify(temp,1,0); } } return 0; }