http://poj.org/problem?id=3667
题意:
有N个房间,M次操作。有两种操作(1)"1a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示入住。(2)"2 b len",把起点为b长度的len的房间清空,即退房。
思路:
区间合并的线段树题。
其实如果单点更新和区间更新做得多了的话,区间合并也就不难了。
对于这道题,我们用线段树维护三个值,从左端开始的连续空房间数,从右边开始的连续空房间数,以及整个区间内最大的连续空房间数。
1 #include<iostream>
2 #include<algorithm>
3 #include<cstring>
4 #include<cstdio>
5 #include<vector>
6 #include<stack>
7 #include<queue>
8 #include<cmath>
9 #include<map>
10 #include<set>
11 using namespace std;
12 typedef long long ll;
13 const int INF = 0x3f3f3f3f;
14 const int maxn=50000+5;
15
16 int n, m;
17
18 struct node //维护从左端开始的最大连续空房间,从右端开始的最大连续空房间,总的最大连续空房间
19 {
20 int l,r;
21 int ls,rs,sum;
22 }t[maxn<<2];
23
24 int lazy[maxn<<2];
25
26
27 void PushUp(int o)
28 {
29 t[o].ls=t[o<<1].ls;
30 t[o].rs=t[o<<1|1].rs;
31 int mid=(t[o].l+t[o].r)>>1;
32 if(t[o].ls==mid-t[o].l+1) t[o].ls+=t[o<<1|1].ls; //如果左半部分都是空房间,那么可以与右半部分的左边空房间连起来
33 if(t[o].rs==t[o].r-mid) t[o].rs+=t[o<<1].rs;
34 t[o].sum=max(max(t[o<<1].sum,t[o<<1|1].sum),t[o<<1].rs+t[o<<1|1].ls);
35 }
36
37 void PushDonw(int o)
38 {
39 if(lazy[o]!=-1)
40 {
41 lazy[o<<1]=lazy[o<<1|1]=lazy[o];
42 if(lazy[o]) //为1的话要将该区间置满
43 {
44 t[o<<1].ls=t[o<<1].rs=t[o<<1].sum=0;
45 t[o<<1|1].ls=t[o<<1|1].rs=t[o<<1|1].sum=0;
46 }
47 else //为0的话要将该区间置空
48 {
49 t[o<<1].ls=t[o<<1].rs=t[o<<1].sum=t[o<<1].r-t[o<<1].l+1;
50 t[o<<1|1].ls=t[o<<1|1].rs=t[o<<1|1].sum=t[o<<1|1].r-t[o<<1|1].l+1;
51 }
52 lazy[o]=-1;
53 }
54 }
55
56 void build(int l, int r, int o)
57 {
58 lazy[o]=-1;
59 t[o].l=l;
60 t[o].r=r;
61 t[o].ls=t[o].rs=t[o].sum=r-l+1;
62 if(l==r) return;
63 int mid=(l+r)>>1;
64 build(l,mid,o<<1);
65 build(mid+1,r,o<<1|1);
66 }
67
68
69 void update(int ql, int qr, int l, int r, int flag, int o)
70 {
71 if(ql<=l && qr>=r)
72 {
73 if(flag) t[o].ls=t[o].rs=t[o].sum=0;
74 else t[o].ls=t[o].rs=t[o].sum=r-l+1;
75 lazy[o]=flag;
76 return;
77 }
78 PushDonw(o);
79 int mid=(l+r)>>1;
80 if(ql<=mid) update(ql,qr,l,mid,flag,o<<1);
81 if(qr>mid) update(ql,qr,mid+1,r,flag,o<<1|1);
82 PushUp(o);
83 }
84
85 int query(int l, int r, int num, int o)
86 {
87 if(l==r) return l;
88 PushDonw(o);
89 int mid=(l+r)>>1;
90 if(t[o<<1].sum>=num) return query(l,mid,num,o<<1);
91 else if(t[o<<1].rs+t[o<<1|1].ls>=num) return mid-t[o<<1].rs+1;
92 else return query(mid+1,r,num,o<<1|1);
93 }
94
95 int main()
96 {
97 //freopen("in.txt","r",stdin);
98 scanf("%d%d",&n,&m);
99 build(1,n,1);
100 while(m--)
101 {
102 int op;
103 scanf("%d",&op);
104 if(op==1)
105 {
106 int x;
107 scanf("%d",&x);
108 if(t[1].sum<x) {puts("0");continue;}
109 int pos=query(1,n,x,1);
110 printf("%d\n",pos);
111 update(pos,pos+x-1,1,n,1,1);
112 }
113 else
114 {
115 int s,t;
116 scanf("%d%d",&s,&t);
117 update(s,s+t-1,1,n,0,1);
118 }
119 }
120 return 0;
121 }
来源:https://www.cnblogs.com/zyb993963526/p/7452142.html