POJ-3667 Hotel 线段树区间合并
题目链接:http://poj.org/problem?id=3667
题意: 有一个旅馆,有N个房间排成一排,现在有两种操作,第一是有X个顾客要入住连续的X个房间,要求输出最小的左端点的位置,不能满足就输出0,第二是将以l开始,长度为X的连续房间清空。
线段树区间合并的经典题目。每个域维护三个值,左端开始的最长连续长度,整个区间的最长连续长度,右端开始的最长连续长度。
1 //STATUS:C++_AC_641MS_2240KB 2 #include <functional> 3 #include <algorithm> 4 #include <iostream> 5 //#include <ext/rope> 6 #include <fstream> 7 #include <sstream> 8 #include <iomanip> 9 #include <numeric> 10 #include <cstring> 11 #include <cassert> 12 #include <cstdio> 13 #include <string> 14 #include <vector> 15 #include <bitset> 16 #include <queue> 17 #include <stack> 18 #include <cmath> 19 #include <ctime> 20 #include <list> 21 #include <set> 22 #include <map> 23 using namespace std; 24 //using namespace __gnu_cxx; 25 //define 26 #define pii pair<int,int> 27 #define mem(a,b) memset(a,b,sizeof(a)) 28 #define lson l,mid,rt<<1 29 #define rson mid+1,r,rt<<1|1 30 #define PI acos(-1.0) 31 //typedef 32 typedef __int64 LL; 33 typedef unsigned __int64 ULL; 34 //const 35 const int N=50010; 36 const int INF=0x3f3f3f3f; 37 const int MOD=100000,STA=8000010; 38 const LL LNF=1LL<<60; 39 const double EPS=1e-8; 40 const double OO=1e15; 41 const int dx[4]={-1,0,1,0}; 42 const int dy[4]={0,1,0,-1}; 43 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; 44 //Daily Use ... 45 inline int sign(double x){return (x>EPS)-(x<-EPS);} 46 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;} 47 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;} 48 template<class T> inline T lcm(T a,T b,T d){return a/d*b;} 49 template<class T> inline T Min(T a,T b){return a<b?a:b;} 50 template<class T> inline T Max(T a,T b){return a>b?a:b;} 51 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);} 52 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);} 53 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));} 54 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));} 55 //End 56 57 int lsum[N<<2],msum[N<<2],rsum[N<<2],c[N<<2]; 58 int n,m,a,b,val; 59 60 void pushdown(int rt,int dl,int dr) 61 { 62 if(c[rt]==-1)return; 63 c[rt<<1]=c[rt<<1|1]=c[rt]; 64 lsum[rt<<1]=msum[rt<<1]=rsum[rt<<1]=c[rt]?0:dl; 65 lsum[rt<<1|1]=msum[rt<<1|1]=rsum[rt<<1|1]=c[rt]?0:dr; 66 } 67 68 void pushup(int rt,int dl,int dr) 69 { 70 c[rt]=c[rt<<1]==c[rt<<1|1]?c[rt<<1]:-1; 71 msum[rt]=Max(msum[rt<<1],msum[rt<<1|1],rsum[rt<<1]+lsum[rt<<1|1]); 72 lsum[rt]=lsum[rt<<1]==dl?lsum[rt<<1]+lsum[rt<<1|1]:lsum[rt<<1]; 73 rsum[rt]=rsum[rt<<1|1]==dr?rsum[rt<<1|1]+rsum[rt<<1]:rsum[rt<<1|1]; 74 } 75 76 void build(int l,int r,int rt) 77 { 78 lsum[rt]=msum[rt]=rsum[rt]=r-l+1; 79 c[rt]=0; 80 if(l==r)return; 81 int mid=(l+r)>>1; 82 build(lson); 83 build(rson); 84 } 85 86 void update(int l,int r,int rt) 87 { 88 if(a<=l && r<=b){ 89 c[rt]=val; 90 lsum[rt]=msum[rt]=rsum[rt]=val?0:r-l+1; 91 return; 92 } 93 int mid=(l+r)>>1; 94 pushdown(rt,mid-l+1,r-mid); 95 if(a<=mid)update(lson); 96 if(b>mid)update(rson); 97 pushup(rt,mid-l+1,r-mid); 98 } 99 100 int query(int l,int r,int rt) 101 { 102 if(l==r)return l; 103 int mid=(l+r)>>1; 104 pushdown(rt,mid-l+1,r-mid); 105 if(msum[rt<<1]>=a)return query(lson); 106 else if(rsum[rt<<1]+lsum[rt<<1|1]>=a)return mid-rsum[rt<<1]+1; 107 else return query(rson); 108 } 109 110 int main() 111 { 112 // freopen("in.txt","r",stdin); 113 int i,j,op,s; 114 while(~scanf("%d%d",&n,&m)) 115 { 116 build(1,n,1); 117 while(m--){ 118 scanf("%d",&op); 119 if(op==1){ 120 scanf("%d",&a); 121 if(msum[1]<a)printf("0\n"); 122 else { 123 s=query(1,n,1); 124 printf("%d\n",s); 125 b=s+a-1;a=s; 126 val=1; 127 update(1,n,1); 128 } 129 } 130 else { 131 scanf("%d%d",&a,&b); 132 b+=a-1;val=0; 133 update(1,n,1); 134 } 135 } 136 } 137 return 0; 138 }