kb-07线段树-12--二分查找区间边界
生活随笔
收集整理的這篇文章主要介紹了
kb-07线段树-12--二分查找区间边界
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 /*
2 hdu4614
3 本題剛開始想能不能記錄該區間最前面開始的點,最后面的點,區間空的數量;但是病不行
4 然后線段樹的本質是區間操作,所以!這題主要就是區間的空的全放滿,只要定出區間的邊界就好辦了;
5 這里用二分查找的方法,現計算滿足數量的區間的尾,因為頭已經確定了,及時不放花也是確定的,只要靠數量定出尾就可以了;
6 然后就是區間修改了;
7 */
8 #include<iostream>
9 #include<cstdio>
10 #include<cstring>
11 #include<algorithm>
12 #define MAX_N 50001
13 using namespace std;
14 int n,m,first,last,num,x;
15 struct tree
16 {
17 int l,r,fir,las,s,same,val;
18 }tr[MAX_N*4];
19 void build(int rt,int l,int r)
20 {
21 tr[rt].l=l;tr[rt].r=r;
22 tr[rt].fir=l;
23 tr[rt].las=r;
24 tr[rt].s=0;
25 tr[rt].val=r-l+1;
26 if(l==r)
27 {
28 tr[rt].same=0;
29 return ;
30 }
31 tr[rt].same=1;
32 int mid=(l+r)/2;
33 build(rt<<1,l,mid);
34 build(rt<<1|1,mid+1,r);
35 }
36 void Pushup(int rt)
37 {
38 int l=rt<<1,r=rt<<1|1;
39 if(tr[l].fir==0)
40 tr[rt].fir=tr[r].fir;
41 else tr[rt].fir=tr[l].fir;
42 if(tr[r].las==0)
43 tr[rt].las=tr[l].las;
44 else tr[rt].las=tr[r].las;
45 tr[rt].val=tr[r].val+tr[l].val;
46
47 }
48 void Pushdown(int rt)
49 {
50 if(tr[rt].l==tr[rt].r)
51 return ;
52 int l=rt<<1,r=rt<<1|1;
53 if(tr[rt].same)
54 {
55 if(tr[rt].s==1)
56 {
57 tr[r].val=tr[l].val=0;
58 tr[r].s=tr[l].s=1;
59 tr[r].fir=tr[l].fir=0;
60 tr[r].las=tr[l].las=0;
61 tr[r].same=tr[l].same=1;
62 tr[rt].same=0;
63 }
64 else
65 {
66 tr[r].val=tr[r].r-tr[r].l+1;
67 tr[l].val=tr[l].r-tr[l].l+1;
68 tr[r].s=tr[l].s=0;
69 tr[r].same=tr[l].same=1;
70 tr[r].fir=tr[r].l;
71 tr[r].las=tr[r].r;
72 tr[l].fir=tr[l].l;
73 tr[l].las=tr[l].r;
74 tr[rt].same=0;
75 }
76 }
77 }
78 void Update1(int rt,int l,int r)
79 {
80 if(x<=0)
81 return ;
82 if(tr[rt].val==0)
83 return ;//在二分查找定區間后,少了這一句所以一直tle
84 if(tr[rt].l==l&&tr[rt].val>0)
85 {
86 if(first==0)
87 first=tr[rt].fir;
88 if(tr[rt].val<=x)
89 {
90 if(last<tr[rt].las)
91 last=tr[rt].las;
92 x-=tr[rt].val;
93 tr[rt].same=1;
94 tr[rt].s=1;
95 tr[rt].val=0;
96 tr[rt].fir=0;
97 tr[rt].las=0;
98 return ;
99 }
100 }
101 if(tr[rt].l==tr[rt].r)
102 return ;
103 Pushdown(rt);
104 int L=rt<<1,R=rt<<1|1;
105 if(l<=tr[L].r)
106 {
107 if(r<=tr[L].r)
108 Update1(L,l,r);
109 else
110 Update1(L,l,tr[L].r);
111 }
112 if(r>=tr[R].l)
113 {
114 if(l>=tr[R].l)
115 Update1(R,l,r);
116 else
117 Update1(R,tr[R].l,r);
118 }
119 Pushup(rt);
120 }
121 void Update2(int rt,int l,int r)
122 {
123 if(tr[rt].l==l&&tr[rt].r==r)
124 {
125 num+=r-l+1-tr[rt].val;
126 tr[rt].val=r-l+1;
127 tr[rt].s=0;
128 tr[rt].same=1;
129 tr[rt].fir=l;
130 tr[rt].las=r;
131 return;
132 }
133 if(tr[rt].l==tr[rt].r)
134 return ;
135 Pushdown(rt);
136 int L=rt<<1,R=rt<<1|1;
137 if(l<=tr[L].r)
138 {
139 if(r<=tr[L].r)
140 Update2(L,l,r);
141 else
142 Update2(L,l,tr[L].r);
143 }
144 if(r>=tr[R].l)
145 {
146 if(l>=tr[R].l)
147 Update2(R,l,r);
148 else
149 Update2(R,tr[R].l,r);
150 }
151 Pushup(rt);
152 }
153 int sum(int rt,int l,int r)
154 {
155 if(tr[rt].l==l&&tr[rt].r==r)
156 {
157 return tr[rt].val;
158 }
159 int ans=0;
160 Pushdown(rt);//因為只是查詢,所以區間整體并沒有變,就沒有必要pushup了;
161 int L=rt<<1,R=rt<<1|1;
162 if(l<=tr[L].r)
163 {
164 if(r<=tr[L].r)
165 ans+= sum(L,l,r);
166 else
167 ans+= sum(L,l,tr[L].r);
168 }
169 if(r>=tr[R].l)
170 {
171 if(l>=tr[R].l)
172 ans+= sum(R,l,r);
173 else
174 ans+= sum(R,tr[R].l,r);
175 }
176 return ans;
177 }
178 int bisearch(int a,int f)
179 {
180 if(sum(1,a,n)==0)
181 return -1;
182 if(sum(1,a,n)<f)//此處的等于號的問題;
183 return n;
184 int l=a,r=n;
185 int ans=a;
186 while(l<=r)
187 {
188 int mid=(l+r)/2;
189 if(sum(1,a,mid)>=f)//以及此處的等于號;
190 {
191 ans=mid;//這里ans的取值;
192 r=mid-1;
193 }
194 else l=mid+1;
195 }
196 return ans;
197 }
198 int main()
199 {
200 int T;
201 scanf("%d",&T);
202 while(T--)
203 {
204 scanf("%d%d",&n,&m);
205 build(1,1,n);
206 for(int i=0;i<m;i++)
207 {
208 int ty,z,y;
209 scanf("%d%d%d",&ty,&z,&y);
210 if(ty==1)
211 {
212 int t=bisearch(z+1,y);
213 if(t!=-1)
214 {
215 x=y;
216 first=0;
217 last=0;
218 Update1(1,z+1,t);
219 printf("%d %d\n",first-1,last-1);
220 }
221 else
222 printf("Can not put any one.\n");
223 }
224 else
225 {
226 num=0;
227 Update2(1,z+1,y+1);
228 printf("%d\n",num);
229 }
230 }
231 printf("\n");
232 }
233 return 0;
234 }
?
轉載于:https://www.cnblogs.com/by-1075324834/p/4543002.html
總結
以上是生活随笔為你收集整理的kb-07线段树-12--二分查找区间边界的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于 Lucene 的桌面文件搜索
- 下一篇: MySQL设置默认引擎和字符集