Tunnel Warfare HDU - 1540
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int N=50000+10; struct node{ int l,r; int maxx; int minn; } tr[N*4]; //保存历史记录,被毁的 int history[N*4]; int n,m; void build(int i,int l,int r) { tr[i].l=l; tr[i].r=r; if(l==r) { //初始化 //i到n的最小 tr[i].minn=n+1; //1到i的最大 tr[i].maxx=0; return; } int mid=(l+r)>>1; build(i<<1,l,mid); build(i<<1|1,mid+1,r); tr[i].maxx=max(tr[i*2].maxx,tr[i*2+1].maxx); tr[i].minn=min(tr[i*2].minn,tr[i*2+1].minn); } //更新最小值 void updateMin(int i,int id,int val) { if(tr[i].l==tr[i].r) { tr[i].minn=val; return; } int mid=tr[i].l+tr[i].r>>1; if(id<=mid) updateMin(i*2,id,val); else updateMin(i*2+1,id,val); tr[i].minn=min(tr[i*2].minn,tr[i*2+1].minn); } //更新最大值 void updateMax(int i,int id,int val) { if(tr[i].l==tr[i].r) { tr[i].maxx=val; return; } int mid=(tr[i].l+tr[i].r)/2; if(id<=mid) updateMax(i*2,id,val); else updateMax(i*2+1,id,val); tr[i].maxx=max(tr[i*2].maxx,tr[i*2+1].maxx); } //查询最小值 int queryMin(int i,int ql,int qr) { //当前区间在目标区间内 if(ql<=tr[i].l&&qr>=tr[i].r) return tr[i].minn; int mid=(tr[i].l+tr[i].r)/2; int res=INF; if(ql<=mid) res=min(res,queryMin(i*2,ql,qr)); if(qr>mid) res=min(res,queryMin(i*2+1,ql,qr)); return res; } //查询最大值 int queryMax(int i,int ql,int qr) { //当前区间在目标区间内 if(ql<=tr[i].l&&qr>=tr[i].r) return tr[i].maxx; int mid=(tr[i].l+tr[i].r)/2; int res=0; if(ql<=mid) res=max(res,queryMax(i*2,ql,qr)); if(qr>mid) res=max(res,queryMax(i*2+1,ql,qr)); return res; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { build(1,1,n); int cnt=0; memset(history,0,sizeof history ); while(m--){ char str[5]; scanf("%s",str); //破坏 if(str[0]=='D') { int x; scanf("%d",&x); //把x对应的值更新成x //初始化时,默认1到x最大到结尾 //x到n最小到开头0 //现在更新为自己, //如果查询的区间包括x,最大最小都会返回x或者其他被毁的 updateMax(1,x,x); updateMin(1,x,x); //记录被毁的 history[++cnt]=x; } //查询 else if(str[0]=='Q') { int x; scanf("%d",&x); int maxx=queryMax(1,1,x); int minn=queryMin(1,x,n); //特判 //如果最大最小相同,说明自身被毁 if(maxx==minn) printf("0\n"); else //从当前点往后的最小,也就是最近的被毁的 //从当前点往前最大的,也就是最近的被毁的 //做差再减去1就是长度 printf("%d\n",minn-maxx-1); } else { //恢复最后被毁的,将对应初始值改回 int temp=history[cnt--]; updateMin(1,temp,n+1); updateMax(1,temp,0); } } } return 0; }