Question]
There are a total of N vacancies, all of which are initially empty. There are two kinds of operations. One is to ask whether there are R consecutive vacancies. If yes, fill all the places with R consecutive vacancies on the leftmost end. If not, leave it empty. The other is to clear all the positions of D starting from U.
[Input]
The first row contains N and M (<= 50000), indicating N vacancies and M operations.
Each row in the next m rows indicates an operation,
If the first number of the row is 1, then a number indicates operation 1.
If the first digit of the row is 2, then two digits are displayed, indicating operation 2.
[Output]
For each operation, if R consecutive vacancies exist, the start point of R consecutive vacancies is output to the left. If not, 0 is output.
Solution:
Lsum indicates the length of the longest consecutive prefix of the current interval, rsum indicates the length of the longest continuous Suffix of the current interval, and msum indicates the length of the longest continuous segment of the current interval. The point is that there is also a cover.-1 indicates that this range is both non-empty and empty. 1 indicates that the entire range is full; 0 indicates that the entire range is empty. Is lazy.
When querying, first, we must satisfy the continuous length. Second:
If the prefix length of the current interval is greater than or equal to the expected length, the left endpoint is returned.
If the longest length of the left child is> = wanted, find it in the left child.
If the continuous range of M is> = wanted, the leftmost end of the left child suffix is directly returned.
Otherwise, you can only find it in the right child.
Question preparation process:
No cover at the beginning, no push_dn, there is only one push_up. If you want to update it, isn't it? That is to say, the child hasn't updated yet, so you must have covered.
Now let's think about it again. It really means that the current interval is the root of the Line Segment tree. How can I forget it...
/* Pro: 0sol: Date: */# include <iostream> # include <cstdio> # include <algorithm> # include <cstring> # include <cmath> # include <queue> # include <set> # include <vector> # define maxn 50010 # define lson l, m, RT <1 # define rson m + 1, R, RT <1 | 1 # define ls RT <1 # define Rs RT <1 | 1int N, q, A, B, OP; using namespace STD; int lsum [maxn <2], rsum [maxn <2], msum [maxn <2], cover [maxn <2]; void build (int l, I Nt r, int RT) {lsum [RT] = rsum [RT] = msum [RT] = r-L + 1; cover [RT] = 0; // If (L = r) return; int M = (L + r)> 1; build (lson); Build (rson);} void push_dn (int rt, int m) {If (cover [RT]! =-1) {cover [ls] = cover [RS] = cover [RT]; lsum [ls] = rsum [ls] = msum [ls] = cover [RT] = 0? M-(M> 1): 0; // lsum [RS] = rsum [RS] = msum [RS] = cover [RT] = 0? (M> 1): 0; cover [RT] =-1 ;}} void push_up (int rt, int m) {lsum [RT] = lsum [ls]; rsum [RT] = rsum [RS]; If (lsum [ls] = m-(M> 1) lsum [RT] + = lsum [RS]; if (rsum [RS] = m> 1) rsum [RT] + = rsum [ls]; msum [RT] = max (msum [ls], msum [RS]); msum [RT] = max (msum [RT], rsum [ls] + lsum [RS]);} // int query (int dis, int L, int R, int RT) {// notonlysuccess version, a bit not very understandable... // If (L = r) return l; // push_dn (RT, R-l + 1); // int M = (L + r)> 1; // If (msum [ls]> = dis) return query (DIS, lson); // If (rsum [ls] + lsum [RS]> = dis) return M-rsum [ls] + 1; // return query (DIS, rson); //} int query (int dis, int L, int R, int RT) {// search for the left endpoint of the leftmost interval of DIS, so I used it for reference and changed it. A returned l (if (lsum [RT]> = dis; push_dn (RT, R-l + 1); int M = (L + r)> 1; if (msum [ls]> = dis) return query (DIS, Lson); If (rsum [ls] + lsum [RS]> = dis) return M-rsum [ls] + 1; return query (DIS, rson );} void Update (int l, int R, int sign, int L, int R, int RT) {If (L <= L & R <= r) {lsum [RT] = rsum [RT] = msum [RT] = Sign = 0? R-l + 1: 0; cover [RT] = sign; return;} push_dn (RT, R-l + 1); int M = (L + r)> 1; if (L <= m) Update (L, R, sign, lson); If (r> m) Update (L, R, sign, rson ); push_up (RT, R-l + 1); //} int main () {While (~ Scanf ("% d", & N, & Q) {build (1, n, 1); For (INT I = 0; I <q; I ++) {scanf ("% d", & OP); If (OP = 1) {scanf ("% d", & ); if (msum [1] <A) puts ("0"); else {int ST = query (A, 1, n, 1 ); printf ("% d \ n", St); Update (St, ST + A-1, 1, 1, n, 1 );}} else {scanf ("% d", & A, & B); Update (A, A + B-1, 0, 1, n, 1 ); // 0 indicates no resident} return 0 ;}