題意:給你n連成一條線的點,m個操作。D x把第x個村莊破壞,Q x查詢與第x個村莊直接和間接相連的村莊數目(包括它自己),R把最早破壞的一個村莊恢複。
除了下面的另一種方法外,現在再做的時候,想到了另一種方法,在查詢的時候,更新尋找到的範圍的左右端點。
/*代碼風格更新後*/#include <iostream>#include <cstdio>#include <cstring>#include <stack>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))const int N=50005;struct node{int lft,rht;int lmx,rmx;int len(){return rht-lft+1;}int mid(){return MID(lft,rht);}void init(){lmx=rmx=len();}void fun(int valu){if(valu==-1) lmx=rmx=0;else lmx=rmx=1;}};int n,m;struct Segtree{node tree[N*4];void up(int ind){tree[ind].lmx=tree[LL(ind)].lmx;tree[ind].rmx=tree[RR(ind)].rmx;if(tree[LL(ind)].lmx==tree[LL(ind)].len())tree[ind].lmx+=tree[RR(ind)].lmx;if(tree[RR(ind)].rmx==tree[RR(ind)].len())tree[ind].rmx+=tree[LL(ind)].rmx;}void build(int lft,int rht,int ind){tree[ind].lft=lft,tree[ind].rht=rht;tree[ind].init();if(lft!=rht){int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid+1,rht,RR(ind));}}void updata(int pos,int ind,int valu){if(tree[ind].lft==tree[ind].rht) tree[ind].fun(valu);else{int mid=tree[ind].mid();if(pos<=mid) updata(pos,LL(ind),valu);else updata(pos,RR(ind),valu);up(ind);}}void query(int pos,int ind,int& x,int& y){if(tree[ind].lft==tree[ind].rht){if(tree[ind].lmx==1) x=y=tree[ind].lft;else x=y=0;}else{int mid=tree[ind].mid();if(pos<=mid) query(pos,LL(ind),x,y);else query(pos,RR(ind),x,y);if(tree[LL(ind)].rht==y) y+=tree[RR(ind)].lmx;if(tree[RR(ind)].lft==x) x-=tree[LL(ind)].rmx;}}}seg;int main(){while(scanf("%d%d",&n,&m)!=EOF){stack<int> q;seg.build(1,n,1);while(m--){char cmd[5];int pos,st,ed;scanf("%s",cmd);if(cmd[0]=='D'){scanf("%d",&pos);seg.updata(pos,1,-1);q.push(pos);}else if(cmd[0]=='Q'){scanf("%d",&pos);seg.query(pos,1,st,ed);if(st==0&&ed==0) puts("0");else printf("%d\n",ed-st+1);//cout<<st<<" "<<ed<<endl;}else{seg.updata(q.top(),1,1); q.pop();}}}return 0;}
題目沒有說有多組資料,不過卻有多組資料,暈死。和hotel那題比較相似,在查詢的時候要注意,要先查詢是否在父區間的左端點的和右端點連續的範圍內,然後查詢是否在左右子區間的串連處。而不是查詢是否在左子區間的左端點的連續的範圍內,這樣會出現錯誤。因為有一種情況是父區間的連續範圍超過了中點。
/*代碼風格更新前*/#include <iostream>#include <cstdio>#include <stack>using namespace std;const int N=50005;struct node{ int left,right; int lmax,rmax; int mid(){return left+(right-left)/2;} int dis(){return right-left+1;}};struct Segtree{ node tree[N*4]; void build(int left,int right,int r) { tree[r].left=left; tree[r].right=right; tree[r].lmax=tree[r].rmax=tree[r].dis(); if(left<right) { int mid=tree[r].mid(); build(left,mid,r*2); build(mid+1,right,r*2+1); } } void updata(int pos,int r,int co) { if(tree[r].left==tree[r].right) tree[r].lmax=tree[r].rmax=co; else { int mid=tree[r].mid(); if(pos<=mid) updata(pos,r*2,co); else if(pos>mid) updata(pos,r*2+1,co); tree[r].lmax=tree[r*2].lmax; tree[r].rmax=tree[r*2+1].rmax; if(tree[r*2].lmax==tree[r*2].dis()) tree[r].lmax+=tree[r*2+1].lmax; if(tree[r*2+1].rmax==tree[r*2+1].dis()) tree[r].rmax+=tree[r*2].rmax; } } int query(int pos,int r) { if(tree[r].left==tree[r].right) return tree[r].lmax; else { int mid=tree[r].mid(); if(tree[r].lmax+tree[r].left>pos) return tree[r].lmax; else if(tree[r*2+1].lmax+tree[r*2+1].left>pos&&tree[r*2].right-tree[r*2].rmax<pos)return tree[r*2].rmax+tree[r*2+1].lmax; else if(tree[r].right-tree[r].rmax<pos) return tree[r].rmax; else if(pos<=mid) return query(pos,r*2); else return query(pos,r*2+1); } }}seg;int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF) { stack<int> q; seg.build(1,n,1); for(int i=0;i<m;i++) { int a; char cmd[5]; scanf("%s",cmd); if(cmd[0]=='D') { scanf("%d",&a); seg.updata(a,1,0); q.push(a); } else if(cmd[0]=='Q') { scanf("%d",&a); printf("%d\n",seg.query(a,1)); } else { seg.updata(q.top(),1,1); q.pop(); } } } return 0;}