HDU 1540 Tunnel Warfare(線段樹)
阿新 • • 發佈:2018-11-03
題意:一條線上的點,D x是破壞這個點,Q x是表示查詢以x所在的最長的連續的點的個數,R是恢復上一次破壞的點。
分析:還是最大連續區間的板題,不過就是變成了單個節點進行更新。直接套用板子稍微更改就好,
#include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; const int maxn=5e4+10; struct node{ int ls,rs,ms; }tree[maxn*4]; int n,m; void build_tree(int l,int r,int i){ tree[i].ls=tree[i].rs=tree[i].ms=r-l+1; if(l==r) return; int mid=l+r>>1; build_tree(l,mid,i<<1); build_tree(mid+1,r,i<<1|1); } bool all_space(int l,int r,int i){ if(tree[i].ls==r-l+1) return 1; return 0; } int query(int t,int l,int r,int i){ if(l==r||tree[i].ms==r-l+1||tree[i].ms==0){ return tree[i].ms; } int mid=l+r>>1; if(t<=mid){ if(t>=mid-tree[i<<1].rs+1){ return query(t,l,mid,i<<1)+query(mid+1,mid+1,r,i<<1|1); }else return query(t,l,mid,i<<1); }else{ if(t<=mid+tree[i<<1|1].ls){ return query(t,mid+1,r,i<<1|1)+query(mid,l,mid,i<<1); }else return query(t,mid+1,r,i<<1|1); } } void change(int t,int l,int r,int i,int flag){ if(l==r){ if(!flag){ tree[i].ls=tree[i].rs=tree[i].ms=0; }else{ tree[i].ls=tree[i].rs=tree[i].ms=1; } return; } int mid=l+r>>1; if(t<=mid) change(t,l,mid,i<<1,flag); else change(t,mid+1,r,i<<1|1,flag); tree[i].ls=tree[i<<1].ls; if(all_space(l,mid,i<<1)) tree[i].ls+=tree[i<<1|1].ls; tree[i].rs=tree[i<<1|1].rs; if(all_space(mid+1,r,i<<1|1)) tree[i].rs+=tree[i<<1].rs; tree[i].ms=max(tree[i<<1].rs+tree[i<<1|1].ls,max(tree[i<<1].ms,tree[i<<1|1].ms)); } int main() { while(~scanf("%d%d",&n,&m)){ stack<int> st; memset(tree,0,sizeof tree); build_tree(1,n,1); while(m--){ char ch; int a; scanf(" %c",&ch); if(ch=='D'){ scanf("%d",&a); change(a,1,n,1,0); st.push(a); }else if(ch=='Q'){ scanf("%d",&a); printf("%d\n",query(a,1,n,1)); }else{ if(st.empty()) continue; change(st.top(),1,n,1,1); st.pop(); } } } return 0; }