思路:原来以为自己已经完全理解了线段树,现在发现其实还差一些火候,做题的时候太拘泥于格式,思路不是很能放开。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 50010 using namespace std; int n,m,top; int stack[MAXN],vis[MAXN]; struct nond{ int l,r,len,ren,mid; }tree[MAXN*4]; void build(int now,int l,int r){ tree[now].l=l;tree[now].r=r; tree[now].len=tree[now].r-tree[now].l+1; tree[now].ren=tree[now].mid=tree[now].len; if(tree[now].l==tree[now].r) return ; int mid=(tree[now].l+tree[now].r)/2; build(now*2,l,mid); build(now*2+1,mid+1,r); } void change(int now,int x,int pos){ if(tree[now].l==tree[now].r){ tree[now].len=tree[now].ren=tree[now].mid=pos; return ; } int mid=(tree[now].l+tree[now].r)/2; if(x<=mid) change(now*2,x,pos); else if(x>mid) change(now*2+1,x,pos); tree[now].len=tree[now*2].len; tree[now].ren=tree[now*2+1].ren; tree[now].mid=max(tree[now*2].mid,tree[now*2+1].mid); tree[now].mid=max(tree[now].mid,tree[now*2].ren+tree[now*2+1].len); if(tree[now*2].len==tree[now*2].r-tree[now*2].l+1) tree[now].len=tree[now*2].len+tree[now*2+1].len; if(tree[now*2+1].ren==tree[now*2+1].r-tree[now*2+1].l+1) tree[now].ren=tree[now*2+1].ren+tree[now*2].ren; } int query(int now,int k){ if(tree[now].l==tree[now].r||tree[now].mid==0||tree[now].mid==tree[now].r-tree[now].l+1) return tree[now].mid; int mid=(tree[now].l+tree[now].r)/2; if(k<=mid){ if(k>=tree[now*2].r-tree[now*2].ren+1) return query(now*2,k)+query(now*2+1,mid+1); else return query(now*2,k); } else{ if(k<=tree[now*2+1].l+tree[now*2+1].len-1) return query(now*2+1,k)+query(now*2,mid); else return query(now*2+1,k); } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ build(1,1,n);top=0; for(int i=1;i<=m;i++){ char c;int x; scanf("\n%c",&c); if(c==‘D‘){ scanf("%d",&x); stack[++top]=x;change(1,x,0); } else if(c==‘Q‘){ scanf("%d",&x); printf("%d\n",query(1,x)); } else change(1,stack[top--],1); } } } /* 7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4 */