Tunnel Warfare
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3047 Accepted Submission(s): 1162
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
1 0 2 4//转载大神的,然后加上自己的理解,不知怎么就错了!#include"stdio.h" #include"string.h" #include"stdlib.h" #include"stack" using namespace std; #define N 50011
int n,m; int hash[N]; struct Segtree { int l,r,mid; int count; }T[4*N];
void build(int l,int r,int k) { T[k].l=l; T[k].r=r; T[k].mid=(l+r)>>1; //叶子节点 if(l==r) { T[k].count=0; return ; } build(l,T[k].mid,2*k); build(T[k].mid+1,r,2*k+1); T[k].count=0; }
int findl(int l,int r,int k) { int ans=0; //左右区间正好等于该节点左右区间 if(T[k].l==l && T[k].r==r && !T[k].count) return r-l+1; //结点为叶子节点 if(T[k].l==T[k].r && T[k].l==l && l==r) return 1-T[k].count; //位于区间左边 if(r<=T[k].mid) ans=findl(l,r,2*k); //位于区间左边 else if(l>T[k].mid) ans=findl(l,r,2*k+1); else { ans=findl(T[k].mid+1,r,2*k+1);//到区间右边搜索 if(ans==r-T[k].mid)///证明该区间为断开,需到中点左边搜索 ans+=findl(l,T[k].mid,2*k); } return ans; }
int findr(int l,int r,int k) { int ans=0; if(T[k].l==l && T[k].r==r && !T[k].count) return r-l+1; if(T[k].l==T[k].r && T[k].l==l && l==r) return 1-T[k].count; if(r<=T[k].mid) ans=findr(l,r,2*k); else if(l>T[k].mid) ans=findr(l,r,2*k+1); else { ans=findr(l,T[k].mid,2*k); if(ans==T[k].mid-l+1) ans+=findr(T[k].mid+1,r,2*k+1); } return ans; }
void Dir(int aim,int dir,int k) { if(T[k].l==T[k].r && T[k].l==aim) { T[k].count+=dir; return ; } if(aim<=T[k].mid) Dir(aim,dir,2*k); else Dir(aim,dir,2*k+1); T[k].count+=dir; //这里不判0了,所以千万要先判一下hash }
int main() { int temp; char str[111]; while(scanf("%d%d",&n,&m)!=-1) { stack<int>st; build(1,n,1); memset(hash,0,sizeof(hash)); while(m--) { scanf("%s",str); if(str[0]!='R') { scanf("%d",&temp); if(str[0]=='D') { st.push(temp); if(hash[temp]) continue; //注意,hash亮了的话,说明被del了 else { hash[temp]=1; Dir(temp,1,1); } } else if(str[0]=='Q') { if(hash[temp]) printf("0\n"); else { //用左右分别查找吧 int a,b; a=findl(1,temp,1); b=findr(temp,n,1); printf("%d\n",a+b-1); } } } else { if(!st.empty()) { temp=st.top(); st.pop(); if(!hash[temp]) continue; hash[temp]=0; Dir(temp,-1,1); } } } } return 0; }