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
");
else {printf("%d
",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
",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
",ans);
}
else if(t1==4){
scanf("%d%d",&t2,&t3);t2++;t3++;tem=0;tep=0;
querty2(1,1,n,t2,t3);
printf("%d
",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
",sum);
}
}
}
while(!s.empty()) s.pop();
}
return 0;
}