线段树之区间合并
1.poj3667 Hotelhttp://poj.org/problem?id=3667
题意:有N个房间,M次操作。有两种操作
(1)"1a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示入住。
(2)"2 b len",把起点为b长度的len的房间清空,即退房
#include <iostream> #include <algorithm> #include <cstdio> #define N 50005 using namespace std; typedef struct node{ int l;int r;int l1;int r1;int len1;int len2;int len;int id; int flag; }node; node d[N<<2]; void push(int root){ if(d[root].flag==1){ d[root<<1].l1=1;d[root<<1].r1=1;d[root<<1].len1=0;d[root<<1].len2=0;d[root<<1].len=0;d[root<<1].id=d[root<<1].l; d[root<<1|1].l1=1;d[root<<1|1].r1=1;d[root<<1|1].len1=0;d[root<<1|1].len2=0;d[root<<1|1].len=0;d[root<<1|1].id=d[root<<1|1].l; d[root<<1].flag=1;d[root<<1|1].flag=1;d[root].flag=-1; } else if(d[root].flag==0){ int t=d[root<<1].r-d[root<<1].l+1; d[root<<1].l1=0;d[root<<1].r1=0;d[root<<1].len1=t;d[root<<1].len2=t;d[root<<1].len=t;d[root<<1].id=d[root<<1].l; t=d[root<<1|1].r-d[root<<1|1].l+1; d[root<<1|1].l1=0;d[root<<1|1].r1=0;d[root<<1|1].len1=t;d[root<<1|1].len2=t;d[root<<1|1].len=t;d[root<<1|1].id=d[root<<1|1].l; d[root<<1].flag=0;d[root<<1|1].flag=0;d[root].flag=-1; } } void up(int root){ d[root].l1=d[root<<1].l1;d[root].r1=d[root<<1|1].r1; if(d[root<<1].len>=d[root<<1|1].len){ d[root].len=d[root<<1].len;d[root].id=d[root<<1].id; } else { d[root].len=d[root<<1|1].len;d[root].id=d[root<<1|1].id; } if(d[root<<1].r1==0&&d[root<<1].r1==d[root<<1|1].l1){ if(d[root<<1].len2+d[root<<1|1].len1>=d[root].len){ d[root].len=d[root<<1].len2+d[root<<1|1].len1; if(d[root<<1].len2+d[root<<1|1].len1==d[root].len) d[root].id=min(d[root].id,d[root<<1].r-d[root<<1].len2+1); else d[root].id=d[root<<1].r-d[root<<1].len2+1; } if(d[root<<1].len2==d[root<<1].r-d[root<<1].l+1) d[root].len1=d[root<<1].len1+d[root<<1|1].len1; else d[root].len1=d[root<<1].len1; if(d[root<<1|1].len1==d[root<<1|1].r-d[root<<1|1].l+1) d[root].len2=d[root<<1|1].len2+d[root<<1].len2; else d[root].len2=d[root<<1|1].len2; } else{ d[root].len1=d[root<<1].len1;d[root].len2=d[root<<1|1].len2; } } void built(int root,int l,int r){ if(l==r){ d[root].l=r;d[root].r=r;d[root].l1=0;d[root].r1=0;d[root].len1=1;d[root].len2=1;d[root].len=1;d[root].id=l; d[root].flag=-1; return ; } int mid=(l+r)>>1; built(root<<1,l,mid); built(root<<1|1,mid+1,r); d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;d[root].flag=-1; up(root); } void update(int root,int l,int r,int t){ if(l<=d[root].l&&d[root].r<=r){ d[root].flag=t; if(t==1){ d[root].l1=1;d[root].r1=1;d[root].len1=0;d[root].len2=0;d[root].len=0;d[root].id=d[root].l; } else{ d[root].l1=0;d[root].r1=0;d[root].len1=d[root].r-d[root].l+1;d[root].len2=d[root].r-d[root].l+1;d[root].len=d[root].r-d[root].l+1; d[root].id=d[root].l; } return ; } push(root); int mid=(d[root].l+d[root].r)>>1; if(l<=mid) update(root<<1,l,r,t); if(r>mid) update(root<<1|1,l,r,t); up(root); } int ans_id; void query(int root,int t){ if(d[root].r-d[root].l+1<t) return ; if(d[root].len<t) return ; if(d[root].r==d[root].l) { ans_id=d[root].l;return ; } push(root); if(d[root<<1].len>=t){ ans_id=d[root].id; query(root<<1,t); } else{ // cout<<d[root<<1].len2<<" "<<d[root<<1|1].len1<<" "<<ans_id<<"------------"<<endl; if(d[root<<1].r1==0&&d[root<<1].r1==d[root<<1|1].l1&&d[root<<1].len2+d[root<<1|1].len1>=t) ans_id=d[root<<1].r-d[root<<1].len2+1; else{ // cout<<d[root].l<<"===="<<d[root].r<<endl; query(root<<1|1,t); } } up(root); } int main(){ int n,m; while(scanf("%d%d",&n,&m)==2){ built(1,1,n); int t1,t2,t3; for(int i=1;i<=m;i++){ scanf("%d",&t1); if(t1==1){ scanf("%d",&t2); ans_id=N; query(1,t2); if(ans_id==N) printf("0\n"); else {printf("%d\n",ans_id); update(1,ans_id,ans_id+t2-1,1); } } else{ scanf("%d%d",&t2,&t3); update(1,t2,t2+t3-1,0); } } } return 0; }
2.hdu3308 LCIS:http://acm.hdu.edu.cn/showproblem.php?pid=3308
给你N个整数,有两种操作,
(1)"U A B",表示把第A个数变成B,
(2)"QAB",表示查询区间[A,B]的最长连续上升序列。
#include<iostream> #include<algorithm> #include<vector> #include<map> #include<set> #include<cstring> #include<cstdio> #include<stack> #include<queue> #define INF 0x3f3f3f3f #define N 100005 using namespace std; typedef struct node{ int first;int end;int l;int lc;int r;int rc;int mmax; }node; node a[N*4]; int b[N]; node pushchuan(node aa,node bb){ int ans; node p; p.first=aa.first;p.end=bb.end; if(aa.r<bb.l){ ans=aa.rc+bb.lc; p.mmax=max(aa.mmax,max(ans,bb.mmax)); p.l=aa.l; if(aa.end-aa.rc+1==aa.first) p.lc=aa.end-aa.first+1+bb.lc; else p.lc=aa.lc; p.r=bb.r; if(bb.end-bb.rc+1==bb.first) p.rc=bb.end-bb.first+1+aa.rc; else p.rc=bb.rc; } else{ p.l=aa.l;p.lc=aa.lc;p.r=bb.r;p.rc=bb.rc; p.mmax=max(aa.mmax,bb.mmax); } return p; } void built(int root,int first,int end){ if(first==end){ a[root].first=first;a[root].end=end;a[root].l=b[first];a[root].lc=1;a[root].r=b[first];a[root].rc=1; a[root].mmax=1; return ; } int mid=(first+end)/2; built(root*2,first,mid); built(root*2+1,mid+1,end); a[root]=pushchuan(a[root*2],a[root*2+1]); // a[root].first=a[root*2].first;a[root].end=a[root*2+1].end; } int maxx; node tt; void Q(int root,int first,int end,int l,int r){ if(l<=first&&end<=r){ if(l==first) tt=a[root]; else tt=pushchuan(tt,a[root]); return ; } int mid=(first+end)/2; if(l<=mid) Q(root*2,first,mid,l,r); if(r>mid) Q(root*2+1,mid+1,end,l,r); } void U(int root,int first,int end,int e,int w){ if(first==end){ a[root].l=w;a[root].r=w; // cout<<"====="<<first<<endl; return ; } int mid=(first+end)/2; if(e<=mid) U(root*2,first,mid,e,w); else U(root*2+1,mid+1,end,e,w); a[root]=pushchuan(a[root*2],a[root*2+1]); // cout<<a[root].first<<" "<<a[root].end<<" "<<a[root].mmax<<" "<<a[root].l<<" "<<a[root].lc<<"========"<<a[root].r<<" "<<a[root].rc<<endl; } int main(){ int T; scanf("%d",&T); int n,m; char ch; while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&b[i]); built(1,1,n); int aa,bb; for(int i=1;i<=m;i++){ scanf(" %c",&ch); if(ch=='U'){ scanf("%d%d",&aa,&bb);aa++; U(1,1,n,aa,bb); } else if(ch=='Q'){ scanf("%d%d",&aa,&bb); aa++;bb++; Q(1,1,n,aa,bb); printf("%d\n",tt.mmax); } } } return 0; }
3.hdu3397 Sequence operation:http://acm.hdu.edu.cn/showproblem.php?pid=3397
有N个为0或为1的数,有M个操作,操作有5种类型。
(1)“0 a b”,表示将区间[a,b]范围内的数全部置0。
(2)“1 a b”,表示将区间[a,b]内的数全部置1。
(3)"2 a b",表示将区间[a,b]内的数0变成1,1变成0。
(4)"3ab",表示查询[a,b]范围内1的数。
(5)"4 a b",表示查询[a,b]范围内最长的连续的1。
题解:情况很多 分开考虑维护即可
#include <bits/stdc++.h> #define N 100005 using namespace std; typedef struct node{ int flag1;int flag2;int l1;int r1;int len1;int len2;int len; int sum;int len11;int len22;int lenn; }node; node d[N<<2]; int a[N]; void swap1(int &a,int &b){ int t=a;a=b;b=t; } void up(int root,int t1,int t2){ int mid=(t1+t2)>>1; d[root].sum=d[root<<1].sum+d[root<<1|1].sum; d[root].len=max(d[root<<1].len,d[root<<1|1].len); d[root].l1=d[root<<1].l1;d[root].r1=d[root<<1|1].r1; if(d[root<<1].r1==1&&d[root<<1].r1==d[root<<1|1].l1){ d[root].len=max(d[root].len,d[root<<1].len2+d[root<<1|1].len1); if(d[root<<1].len1==mid-t1+1) d[root].len1=d[root<<1].len1+d[root<<1|1].len1; else d[root].len1=d[root<<1].len1; if(d[root<<1|1].len2==t2-mid) d[root].len2=d[root<<1|1].len2+d[root<<1].len2; else d[root].len2=d[root<<1|1].len2; } else{ d[root].len1=d[root<<1].len1;d[root].len2=d[root<<1|1].len2; } d[root].lenn=max(d[root<<1].lenn,d[root<<1|1].lenn); if(d[root<<1].r1==0&&d[root<<1].r1==d[root<<1|1].l1){ d[root].lenn=max(d[root].lenn,d[root<<1].len22+d[root<<1|1].len11); if(d[root<<1].len11==mid-t1+1) d[root].len11=d[root<<1].len11+d[root<<1|1].len11; else d[root].len11=d[root<<1].len11; if(d[root<<1|1].len22==t2-mid) d[root].len22=d[root<<1|1].len22+d[root<<1].len22; else d[root].len22=d[root<<1|1].len22; } else{ d[root].len11=d[root<<1].len11;d[root].len22=d[root<<1|1].len22; } } void push(int root,int t1,int t2){ int mid=(t1+t2)>>1; if(d[root].flag1!=-1){ d[root<<1].flag2=0;d[root<<1|1].flag2=0;d[root<<1].flag1=d[root].flag1;d[root<<1|1].flag1=d[root].flag1; if(d[root].flag1==0){ d[root<<1].l1=0;d[root<<1].r1=0;d[root<<1].len1=0;d[root<<1].len2=0;d[root<<1].len=0;d[root<<1].sum=0; d[root<<1].len11=mid-t1+1;d[root<<1].len22=mid-t1+1;d[root<<1].lenn=mid-t1+1; d[root<<1|1].l1=0;d[root<<1|1].r1=0;d[root<<1|1].len1=0;d[root<<1|1].len2=0;d[root<<1|1].len=0;d[root<<1|1].sum=0; d[root<<1|1].len11=t2-mid;d[root<<1|1].len22=t2-mid;d[root<<1|1].lenn=t2-mid; } else{ d[root<<1].l1=1;d[root<<1].r1=1;d[root<<1].len1=(mid-t1+1);d[root<<1].len2=(mid-t1+1); d[root<<1].len=mid-t1+1;d[root<<1].sum=mid-t1+1; d[root<<1].len11=0;d[root<<1].len22=0;d[root<<1].lenn=0; int t=t2-mid; d[root<<1|1].l1=1;d[root<<1|1].r1=1;d[root<<1|1].len1=t;d[root<<1|1].len2=t;d[root<<1|1].len=t;d[root<<1|1].sum=t; d[root<<1|1].len11=0;d[root<<1|1].len22=0;d[root<<1|1].lenn=0; } d[root].flag1=-1; if(d[root].flag2%2==1){ d[root<<1].flag2=1;d[root<<1|1].flag2=1; d[root<<1].sum=(mid-t1+1-d[root<<1].sum);d[root<<1|1].sum=(t2-mid-d[root<<1|1].sum); swap(d[root<<1].len,d[root<<1].lenn);swap(d[root<<1].len1,d[root<<1].len11);swap(d[root<<1].len2,d[root<<1].len22); swap(d[root<<1|1].len,d[root<<1|1].lenn);swap(d[root<<1|1].len1,d[root<<1|1].len11);swap(d[root<<1|1].len2,d[root<<1|1].len22); d[root<<1].l1=(d[root<<1].l1==0)?1:0;d[root<<1].r1=(d[root<<1].r1==0)?1:0; d[root<<1|1].l1=(d[root<<1|1].l1==0)?1:0;d[root<<1|1].r1=(d[root<<1|1].r1==0)?1:0; } d[root].flag2=0; } else{ if(d[root].flag2%2==1){ d[root<<1].flag2=(d[root<<1].flag2+1)%2;d[root<<1|1].flag2=(d[root<<1|1].flag2+1)%2; d[root<<1].sum=(mid-t1+1-d[root<<1].sum);d[root<<1|1].sum=(t2-mid-d[root<<1|1].sum); swap(d[root<<1].len,d[root<<1].lenn);swap(d[root<<1].len1,d[root<<1].len11);swap(d[root<<1].len2,d[root<<1].len22); swap(d[root<<1|1].len,d[root<<1|1].lenn);swap(d[root<<1|1].len1,d[root<<1|1].len11);swap(d[root<<1|1].len2,d[root<<1|1].len22); d[root<<1].l1=(d[root<<1].l1==0)?1:0;d[root<<1].r1=(d[root<<1].r1==0)?1:0; d[root<<1|1].l1=(d[root<<1|1].l1==0)?1:0;d[root<<1|1].r1=(d[root<<1|1].r1==0)?1:0; } d[root].flag2=0; } } void built(int root,int l,int r){ if(l==r){ d[root].flag1=-1;d[root].flag2=0;d[root].l1=a[l];d[root].r1=a[l];d[root].len1=a[l];d[root].len2=a[l]; d[root].len=a[l];d[root].sum=a[l]; d[root].len11=(d[root].len1==1)?0:1;d[root].len22=d[root].len11;d[root].lenn=d[root].len11; return ; } int mid=(l+r)>>1; built(root<<1,l,mid); built(root<<1|1,mid+1,r); d[root].flag1=-1;d[root].flag2=0; up(root,l,r); } void update1(int root,int l,int r,int l1,int r1,int t){ if(l1<=l&&r<=r1){ d[root].flag1=t;d[root].flag2=0; if(t==0){ d[root].l1=0;d[root].r1=0;d[root].len1=0;d[root].len2=0;d[root].len=0;d[root].sum=0; d[root].len11=r-l+1;d[root].len22=r-l+1;d[root].lenn=r-l+1; } else{ d[root].l1=1;d[root].r1=1;d[root].len1=(r-l+1);d[root].len2=(r-l+1); d[root].len=r-l+1;d[root].sum=r-l+1; d[root].len11=0;d[root].len22=0;d[root].lenn=0; } // cout<<l<<" "<<r<<"====="<<d[root].sum<<endl; return ; } push(root,l,r); int mid=(l+r)>>1; if(l1<=mid) update1(root<<1,l,mid,l1,r1,t); if(r1>mid) update1(root<<1|1,mid+1,r,l1,r1,t); //cout<<l<<" "<<r<<endl; up(root,l,r); } void update2(int root,int l,int r,int l1,int r1){ if(l1<=l&&r<=r1){ d[root].flag2++; d[root].sum=(r-l+1-d[root].sum); swap(d[root].len,d[root].lenn);swap(d[root].len1,d[root].len11);swap(d[root].len2,d[root].len22); d[root].l1=(d[root].l1==0)?1:0;d[root].r1=(d[root].r1==0)?1:0; return ; } push(root,l,r); int mid=(l+r)>>1; if(l1<=mid) update2(root<<1,l,mid,l1,r1); if(mid<r1) update2(root<<1|1,mid+1,r,l1,r1); up(root,l,r); //cout<<l<<"====="<<r<<" "<<d[root].len<<endl; } int ans; void querty1(int root,int l,int r,int l1,int r1){ if(l1<=l&&r<=r1){ // cout<<l<<"====="<<r<<" "<<d[root].sum<<endl; ans+=d[root].sum; return ; } push(root,l,r); int mid=(l+r)>>1; if(l1<=mid) querty1(root<<1,l,mid,l1,r1); if(r1>mid) querty1(root<<1|1,mid+1,r,l1,r1); up(root,l,r); //cout<<l<<" "<<r<<"======"<<d[root].sum<<endl; } bool tem;int ans1;node pp;bool tep; void querty2(int root,int l,int r,int l1,int r1){ if(l1<=l&&r<=r1){ // cout<<l<<"===="<<r<<" "<<d[root].len<<endl; if(tem==0){ pp=d[root];ans1=pp.len;tem=1; if(pp.len1==(r-l+1)) tep=1; } else{ ans1=max(ans1,d[root].len); if(pp.r1==1&&d[root].l1==pp.r1){ ans1=max(ans1,pp.len2+d[root].len1); if(tep==1) pp.len1=pp.len1+d[root].len1; if(tep==1&&d[root].len1==(r-l+1)) tep=1; else tep=0; if(d[root].len2==(r-l+1)) pp.len2=d[root].len2+pp.len2; else pp.len2=d[root].len2; } else pp.len2=d[root].len2; pp.r1=d[root].r1; } // cout<<pp.len1<<" "<<pp.len2<<endl; // cout<<l<<" "<<r<<" "<<"========"<<ans1<<endl; return ; } push(root,l,r); int mid=(l+r)>>1; if(l1<=mid) querty2(root<<1,l,mid,l1,r1); if(r1>mid) querty2(root<<1|1,mid+1,r,l1,r1); up(root,l,r); } int main(){ int T;scanf("%d",&T); while(T--){ int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); built(1,1,n); for(int i=1;i<=m;i++){ int t1,t2,t3;scanf("%d",&t1); if(t1==0){ scanf("%d%d",&t2,&t3);t2++;t3++; update1(1,1,n,t2,t3,0); } else if(t1==1){ scanf("%d%d",&t2,&t3);t2++;t3++; update1(1,1,n,t2,t3,1); } else if(t1==2){ scanf("%d%d",&t2,&t3);t2++;t3++; update2(1,1,n,t2,t3); } else if(t1==3){ scanf("%d%d",&t2,&t3);t2++;t3++; // cout<<t2<<" "<<t3<<endl; ans=0; querty1(1,1,n,t2,t3); printf("%d\n",ans); } else if(t1==4){ scanf("%d%d",&t2,&t3);t2++;t3++;tem=0;tep=0; querty2(1,1,n,t2,t3); printf("%d\n",ans1); } } } return 0; }
hdu1540 Tunnel Warfare:http://acm.hdu.edu.cn/showproblem.php?pid=1540
有N个村子排成一条直线,每个村子都连接了它的左右两个村子(除了最左边和最右边的外),有3种操作,
(1)"D x",表示将第x个村子摧毁。
(2)"Qx",表示查询与第x个村子直接和间接相连的村子有多少个。
(3)"R",表示将最早摧毁的村子复原。解题报告Here。
题意:没啥好说的傻逼维护区间合并....XJB搞一搞 栈维护就行
#include <bits/stdc++.h> #define N 50005 using namespace std; typedef struct node{ int first;int end;int l;int r; }node; node a[4*N]; int b[N]; bool vis[N]; node pushchuan(node aa,node bb){ node p; p.first=aa.first;p.end=bb.end; if(aa.l==(aa.end-aa.first+1)){ p.l=aa.l+bb.l; } else{ p.l=aa.l; } if(bb.r==(bb.end-bb.first+1)){ p.r=bb.r+aa.r; } else{ p.r=bb.r; } return p; } void built(int root,int first,int end){ if(first==end){ a[root].first=first;a[root].end=end;a[root].l=1;a[root].r=1; return ; } int mid=(first+end)>>1; built(root*2,first,mid); built(root*2+1,mid+1,end); node p=pushchuan(a[root*2],a[root*2+1]); a[root]=p; } void update(int root,int first,int end,int e,int w){ if(first==end){ if(w==1){ a[root].l=1;a[root].r=1; } else{ a[root].l=0;a[root].r=0; } return ; } int mid=(first+end)>>1; if(e<=mid) update(root*2,first,mid,e,w); else update(root*2+1,mid+1,end,e,w); node p=pushchuan(a[root*2],a[root*2+1]); a[root]=p; } int sum; void query(int root,int first,int end,int e){ if(first==end){ sum++; return ; } int mid=(first+end)>>1; if(e<=mid){ if(a[root*2].r>=(a[root*2].end-e+1)) sum+=a[root*2+1].l; query(root*2,first,mid,e); } else{ if(a[root*2+1].l>=(e-a[root*2+1].first+1)) sum+=a[root*2].r; query(root*2+1,mid+1,end,e); } } int main(){ int n,m; while(scanf("%d%d",&n,&m)==2){ built(1,1,n); char ch;int t1; stack<int>s; memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++){ scanf(" %c",&ch); if(ch=='D'){ scanf("%d",&t1); update(1,1,n,t1,0); s.push(t1); vis[t1]=1; } else if(ch=='R'){ t1=s.top();s.pop(); vis[t1]=0; update(1,1,n,t1,1); } else { scanf("%d",&t1); if(vis[t1]==1) cout<<0<<endl; else{ sum=0; query(1,1,n,t1); printf("%d\n",sum); } } } while(!s.empty()) s.pop(); } return 0; }