首页 > 代码库 > poj3667---Hotel 线段树区间合并,区间更新
poj3667---Hotel 线段树区间合并,区间更新
题意:有N个房间,M次操作。有两种操作(1)"1 a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示入住。(2)"2 b len",把起点为b长度的len的房间清空,即退房。三个数组分别记录 lsum区间左值 rsum区间右值 sum区间最大值。
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cctype> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 using namespace std; 16 typedef unsigned long long ull; 17 typedef long long ll; 18 const int inf = 0x3f3f3f3f; 19 const double eps = 1e-8; 20 template <class T> 21 inline bool scan_d(T &ret) 22 { 23 char c; 24 int sgn; 25 if(c=getchar(),c==EOF) return 0; 26 while(c!=‘-‘&&(c<‘0‘||c>‘9‘)) c=getchar(); 27 sgn=(c==‘-‘)?-1:1; 28 ret=(c==‘-‘)?0:(c-‘0‘); 29 while(c=getchar(),c>=‘0‘&&c<=‘9‘) ret=ret*10+(c-‘0‘); 30 ret*=sgn; 31 return 1; 32 } 33 34 const int maxn = 5e4+10; 35 int lv[maxn<<2],rv[maxn<<2], setv[maxn<<2]; //lv,rv数组可有可无,lsum rsum数组已经包含了他们的意义。 36 int lsum[maxn<<2],rsum[maxn<<2],sum[maxn<<2]; 37 38 void push_up(int l,int r,int pos) 39 { 40 lv[pos] = lv[pos<<1]; 41 rv[pos] = rv[pos<<1|1]; 42 lsum[pos] = lsum[pos<<1]; 43 rsum[pos] = rsum[pos<<1|1]; 44 sum[pos] = max(sum[pos<<1],sum[pos<<1|1]); 45 sum[pos] = max(sum[pos],rsum[pos<<1]+lsum[pos<<1|1]); 46 int mid = (l + r) >> 1; 47 if (rv[pos<<1] ==lv[pos<<1|1] && !rv[pos<<1]) 48 { 49 if (lsum[pos<<1] == mid - l + 1) 50 lsum[pos] += lsum[pos<<1|1]; 51 if (rsum[pos<<1|1] == r - mid) 52 rsum[pos] += rsum[pos<<1]; 53 sum[pos] = max(sum[pos],rsum[pos<<1]+lsum[pos<<1|1]); 54 } 55 } 56 57 void push_down(int l,int r,int pos) 58 { 59 if (~setv[pos]) 60 { 61 int mid = (l + r) >> 1; 62 setv[pos<<1] = setv[pos<<1|1] = setv[pos]; 63 lv[pos<<1] = setv[pos]; 64 lv[pos<<1|1] = setv[pos]; 65 rv[pos<<1] = setv[pos]; 66 rv[pos<<1|1] = setv[pos]; 67 lsum[pos<<1] = (setv[pos] ? 0 : (mid-l+1)); 68 rsum[pos<<1] = (setv[pos] ? 0 : (mid-l+1)); 69 lsum[pos<<1|1] = (setv[pos] ? 0 : (r-mid)); 70 rsum[pos<<1|1] = (setv[pos] ? 0 : (r-mid)); 71 sum[pos<<1] = (setv[pos] ? 0 : (mid-l+1)); 72 sum[pos<<1|1] = (setv[pos] ? 0 : (r-mid)); 73 setv[pos] = -1; 74 } 75 } 76 77 void build (int l,int r,int pos) 78 { 79 if (l == r) 80 { 81 rv[pos] = lv[pos] = 0; 82 sum[pos] = lsum[pos] = rsum[pos] = 1; 83 return; 84 } 85 int mid = (l + r) >> 1; 86 build(l,mid,pos<<1); 87 build(mid+1,r,pos<<1|1); 88 push_up(l,r,pos); 89 } 90 91 void update(int l,int r,int pos,int ua,int ub,int val) 92 { 93 if (ua <= l && ub >= r) 94 { 95 setv[pos] = val; 96 lv[pos] = val; 97 rv[pos] = val; 98 lsum[pos] = (val ? 0 : (r-l+1)); 99 rsum[pos] = (val ? 0 : (r-l+1));100 sum[pos] = (val ? 0 : (r-l+1));101 return;102 }103 int mid = (l + r) >> 1;104 push_down(l,r,pos);105 if (ua <= mid)106 update(l,mid,pos<<1,ua,ub,val);107 if (ub > mid)108 update(mid+1,r,pos<<1|1,ua,ub,val);109 push_up(l,r,pos);110 }111 112 int query(int l,int r,int pos,int x)113 {114 if (lsum[pos] >= x)115 {116 return l;117 118 }119 int mid = (l + r) >> 1;120 push_down(l,r,pos);121 if (sum[pos<<1] >= x)122 return query(l,mid,pos<<1,x);123 /*else if (rsum[pos<<1]&&rsum[pos<<1] + lsum[pos<<1|1] >= x) //注释部分是错误的,,看起来很像但是不一样的124 return query(l,mid,pos<<1,rsum[pos<<1]);*/125 else if (rsum[pos<<1] + lsum[pos<<1|1] >= x)126 return mid+1-rsum[pos<<1];127 else128 return query(mid+1,r,pos<<1|1,x);129 }130 131 int main(void)132 {133 #ifndef ONLINE_JUDGE134 freopen("in.txt","r",stdin);135 #endif136 int n,q;137 while (~scanf ("%d%d",&n,&q))138 {139 build(1,n,1);140 memset(setv,-1,sizeof(setv));141 for (int i = 0; i < q; i++)142 {143 int op,x,y;144 scanf ("%d",&op);145 if (op == 1)146 {147 scanf ("%d",&x);148 if (sum[1] < x)149 {150 printf("0\n");151 continue;152 }153 int p = query(1,n,1,x);154 printf("%d\n",p);155 update(1,n,1,p,p+x-1,1);156 }157 else158 {159 scanf ("%d%d",&x,&y);160 update(1,n,1,x,y+x-1,0);161 }162 }163 }164 return 0;165 }
poj3667---Hotel 线段树区间合并,区间更新
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。