http://poj.org/problem?id=2892
此代码在POJ上能过 在hdu上过不了
题目大意:
n个村庄相连 三种操作
D 摧毁一个村庄
Q 查询包括此村庄在内和此村庄直接和间接相连的村庄数
R 修复上一个被摧毁的村庄
Ttree 写的很烂呀
思路:
将摧毁的村庄插入二叉树中
每次询问 就查找它左边和右边最近被摧毁的村庄 就可以知道答案了
修复一个村庄 就把它在树中删除
代码及其注释:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> #include<stack> using namespace std; const int N=50010; struct node { int k; int l,r,f; }mem[N]; int destroy[N];//是否被摧毁 int treehead,n;//头结点 和村庄个数 stack<int>str;//保存被摧毁的村庄 void RightTurn(int i)//右转 { int f=mem[i].f; int l=mem[i].l; if(f==-1) { mem[l].f=-1; treehead=l; }else { if(mem[f].l==i) mem[f].l=l; else mem[f].r=l; mem[l].f=f; } mem[i].l=mem[l].r; if(mem[l].r!=-1) mem[mem[l].r].f=i; mem[l].r=i; mem[i].f=l; } void LeftTurn(int i)//左转 { int f=mem[i].f; int r=mem[i].r; if(f==-1) { mem[r].f=-1; treehead=r; }else { if(mem[f].l==i) mem[f].l=r; else mem[f].r=r; mem[r].f=f; } mem[i].r=mem[r].l; if(mem[r].l!=-1) mem[mem[r].l].f=i; mem[r].l=i; mem[i].f=r; } void insert(int i,int k)//插入 { if(k<i) { if(mem[i].l!=-1) { insert(mem[i].l,k); if(mem[mem[i].l].k<mem[i].k) { RightTurn(i); } }else { mem[i].l=k; mem[k].f=i; } }else { if(mem[i].r!=-1) { insert(mem[i].r,k); if(mem[mem[i].r].k<mem[i].k) { LeftTurn(i); } }else { mem[i].r=k; mem[k].f=i; } } } void dele(int i,int k)//删除 { if(i<k) { dele(mem[i].r,k); }else if(i>k) { dele(mem[i].l,k); }else { int x=i; while(mem[x].l!=-1||mem[x].r!=-1) { if(mem[x].l!=-1) { RightTurn(x); }else { LeftTurn(x); } } if(mem[x].f==-1) { treehead=-1;return; } if(mem[mem[x].f].l==x) mem[mem[x].f].l=-1; if(mem[mem[x].f].r==x) mem[mem[x].f].r=-1; } } void LeastLeft(int i,int k,int *L)//求最近左被摧毁村庄 { if(i==-1) { return; } if(k<=i) { LeastLeft(mem[i].l,k,L); }else if(k>i) { *L=max(*L,i); LeastLeft(mem[i].r,k,L); } } void LeastRight(int i,int k,int *R)//求最近右被摧毁村庄 { if(i==-1) { return; } if(k<i) { *R=min(*R,i); LeastRight(mem[i].l,k,R); }else if(k>=i) { LeastRight(mem[i].r,k,R); } } void begin()//初始化一些内容 { while(!str.empty()) str.pop(); memset(destroy,0,sizeof(destroy)); treehead=-1; } int main() { int m; while(scanf("%d %d",&n,&m)!=EOF) { begin(); char c; int i; for(int k=1;k<=m;++k) { getchar(); scanf("%c",&c); if(c=='D') { scanf("%d",&i); mem[i].l=mem[i].r=-1; mem[i].k=k; if(treehead==-1)//如果树是空的 { treehead=i; mem[i].f=-1; }else { insert(treehead,i);//否则 插入 } str.push(i); ++destroy[i];//记录 }else if(c=='Q') { int ans,L,R; scanf("%d",&i); if(destroy[i]>0)//特殊情况 { ans=0; }else { L=0; LeastLeft(treehead,i,&L); R=n+1; LeastRight(treehead,i,&R); ans=R-L-1; } printf("%d\n",ans); }else { if(str.empty()) continue; dele(treehead,str.top());//删点 并记录 --destroy[str.top()]; str.pop(); } } } return 0; }