~~~~
线段树区间合并~
两种操作:
1、输出满足连续区间最左边的值。
2、更新一段连续区间。
题目链接:http://poj.org/problem?id=3667
~~~~
#include<cstdio> #include<cstring> #include<algorithm> #define INF 0x7fffffff #define lson rt<<1,s,m #define rson rt<<1|1,m+1,e #define N 55555 using namespace std; struct node { int v; int lm,rm,sm; }tre[N<<2]; void build(int rt,int s,int e) { tre[rt].v=-1; tre[rt].lm=tre[rt].rm=tre[rt].sm=e-s+1; if(s==e) return ; int m=(s+e)>>1; build(lson); build(rson); } void pushdown(int rt,int m) //成段更新操作。 { if(tre[rt].v!=-1) { tre[rt<<1].v=tre[rt<<1|1].v=tre[rt].v; tre[rt<<1].lm=tre[rt<<1].rm=tre[rt<<1].sm=tre[rt].v? 0:m-(m>>1); tre[rt<<1|1].lm=tre[rt<<1|1].rm=tre[rt<<1|1].sm=tre[rt].v? 0:m>>1; tre[rt].v=-1; } } void pushup(int rt,int m) //区间合并操作。 { tre[rt].lm=tre[rt<<1].lm; tre[rt].rm=tre[rt<<1|1].rm; if(tre[rt].lm==m-(m>>1)) tre[rt].lm+=tre[rt<<1|1].lm; if(tre[rt].rm==(m>>1)) tre[rt].rm+=tre[rt<<1].rm; tre[rt].sm=max(tre[rt<<1].sm,max(tre[rt<<1|1].sm,tre[rt<<1].rm+tre[rt<<1|1].lm)); } int query(int n,int rt,int s,int e) { if(s==e) return s; pushdown(rt,e-s+1); int m=(s+e)>>1; //因为要输出最左边的位置。 if(tre[rt<<1].sm>=n) return query(n,lson); else if(tre[rt<<1].rm+tre[rt<<1|1].lm>=n) return m-tre[rt<<1].rm+1; //两个子区间的中间区域。 else return query(n,rson); } void update(int l,int r,int v,int rt,int s,int e) { if(l==s && r==e) { tre[rt].v=v; tre[rt].lm=tre[rt].rm=tre[rt].sm=v? 0:e-s+1; return ; } pushdown(rt,e-s+1); int m=(s+e)>>1; if(r<=m) update(l,r,v,lson); else if(l>m) update(l,r,v,rson); else { update(l,m,v,lson); update(m+1,r,v,rson); } pushup(rt,e-s+1); } int main() { int n,m; while(~scanf("%d%d",&n,&m)) { build(1,1,n); for(int i=0;i<m;i++) { int op; scanf("%d",&op); if(op==1) { int num; scanf("%d",&num); if(tre[1].sm>=num) { int k=query(num,1,1,n); printf("%d\n",k); update(k,k+num-1,1,1,1,n); } else puts("0"); } else { int k,num; scanf("%d %d",&k,&num); update(k,k+num-1,0,1,1,n); } } } return 0; }
POJ 3667 Hotel.,布布扣,bubuko.com
原文:http://blog.csdn.net/darwin_/article/details/38499795