标签:线段树
7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
1 0 2 4
这题可以用线段树做,数据区间合并,这里要注意题意,每次R恢复的是上次炸过的地方,不管是不是重复炸过,如D 6 D 3 D 3 D 3 R R,那么6那个点并没有恢复,这里WA了快10次。。。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define maxn 50005 char s[10]; int a[maxn],sum,vis[maxn]; struct node{ int l,r,llen,rlen,tlen; }b[4*maxn]; int max(int a,int b){ return a>b?a:b; } void build(int l,int r,int i) { int mid; b[i].l=l;b[i].r=r;b[i].llen=b[i].rlen=b[i].tlen=(b[i].r-b[i].l+1); if(l==r)return; mid=(l+r)/2; build(l,mid,i*2); build(mid+1,r,i*2+1); } void update(int id,int panduan,int i) { int mid; if(b[i].l==b[i].r){ if(panduan==1){ b[i].llen=b[i].tlen=b[i].rlen=0; } else{ b[i].llen=b[i].tlen=b[i].rlen=1; } return; } if(b[i*2].r>=id)update(id,panduan,i*2); else update(id,panduan,i*2+1); b[i].tlen=b[i*2].rlen+b[i*2+1].llen; b[i].llen=b[i*2].llen;b[i].rlen=b[i*2+1].rlen; if(b[i*2].llen==b[i*2].r-b[i*2].l+1){ b[i].llen+=b[i*2+1].llen; } if(b[i*2+1].rlen==b[i*2+1].r-b[i*2+1].l+1){ b[i].rlen+=b[i*2].rlen; } } int question(int id,int i) { int mid; if(b[i].l==b[i].r || b[i].tlen==(b[i].r-b[i].l+1) || b[i].tlen==0){ return b[i].tlen; } if(b[i*2].r>=id){ if(b[i*2].r-b[i*2].rlen+1<=id){ return b[i*2].rlen+b[i*2+1].llen; } else return question(id,i*2); } else{ if(b[i*2+1].l+b[i*2+1].llen-1>=id){ return b[i*2].rlen+b[i*2+1].llen; } else return question(id,i*2+1); } } int main() { int n,m,i,j,c,num,flag; while(scanf("%d%d",&n,&m)!=EOF) { build(1,n,1); num=0; memset(vis,0,sizeof(vis)); for(i=1;i<=m;i++){ scanf("%s",s); if(s[0]=='D'){ scanf("%d",&c); a[++num]=c; update(c,1,1); } else if(s[0]=='R'){ if(num>=1)update(a[num--],2,1); } else if(s[0]=='Q'){ scanf("%d",&c); flag=0; printf("%d\n",question(c,1)); } } } return 0; }
标签:线段树
原文地址:http://blog.csdn.net/kirito_acmer/article/details/46128739