POJ 2892 Tunnel Warfare
题目大意:
线段树区间查询题目,给出区间长度和截断的点,问当前点上未截断的区间最大是多少。未被截断的可以截断,
截断的可以修复。
解题思路:
直接上线段树就行。更新的是点, 查询的是区间~~
下面是代码:
#include <stdio.h> const int Max=50005; struct node { int lsum,rsum,mnum,sum; } node[Max<<2]; int stack1[Max],top; int max(int a,int b) { if(a<b)a=b; return a; } void PushUp(int tr) { node[tr].sum=node[tr<<1].sum+node[tr<<1|1].sum; if(node[tr].sum) { if(!node[tr<<1].sum) { node[tr].lsum=node[tr<<1].mnum+node[tr<<1|1].lsum; } else node[tr].lsum=node[tr<<1].lsum; if(!node[tr<<1|1].sum) { node[tr].rsum=node[tr<<1|1].mnum+node[tr<<1].rsum; } else node[tr].rsum=node[tr<<1|1].rsum; node[tr].mnum=max(max(node[tr<<1].mnum,node[tr<<1|1].mnum),node[tr<<1].rsum+node[tr<<1|1].lsum); } else { node[tr].lsum=node[tr].rsum=node[tr].mnum=node[tr<<1].mnum+node[tr<<1|1].mnum; } } void update(int p,int add ,int l,int r,int tr) { if(l==r) { node[tr].sum=add; if(!node[tr].sum) { node[tr].mnum=1; node[tr].lsum=1; node[tr].rsum=1; } else { node[tr].mnum=0; node[tr].lsum=0; node[tr].rsum=0; } return; } int m=(l+r)>>1; if(p<=m)update(p,add,l,m,tr<<1); else update(p,add,m+1,r,tr<<1|1); PushUp(tr); } int query(int p,int l,int r,int tr) { if(l==r||!node[tr].sum||!node[tr].mnum) { return node[tr].mnum; } int m=(l+r)>>1,ans=0; if(p<=m) { if(p>=m-node[tr<<1].rsum+1) { return node[tr<<1].rsum+node[tr<<1|1].lsum; } else return query(p,l,m,tr<<1); } else { if(p<=m+node[tr<<1|1].lsum) { return node[tr<<1|1].lsum+node[tr<<1].rsum; } else return query(p,m+1,r,tr<<1|1); } } void build(int l,int r ,int tr) { node[tr].mnum=node[tr].lsum=node[tr].rsum=1; node[tr].sum=0; if(l==r)return; int m=(l+r)>>1; build(l,m,tr<<1); build(m+1,r,tr<<1|1); PushUp(tr); } int main() { int n,m,x; char s[3]; while(scanf("%d%d",&n,&m)!=EOF) { top=0; build(1,n,1); for(int i=0; i<m; i++) { scanf("%s",s); if(s[0]=='D') { scanf("%d",&x); update(x,1,1,n,1); stack1[top++]=x; } else if(s[0]=='Q') { scanf("%d",&x); printf("%d\n",query(x,1,n,1)); } else if(s[0]=='R') { top--; update(stack1[top],0,1,n,1); } } } return 0; }