To yourself & \ (rng\) : Hubris
\ (lpl\) refueling!
P2572 [SCOI2010] sequence action
Title Description
LXHGWW recently received a 01 sequence containing the n number, which is either 0 or 1, and now there are five transformations and inquiry operations for this sequence:
0 A B turns all the numbers in the [a, b] interval to 0
1 A B turns all the numbers in the [a, b] interval to 1
2 A B All the numbers in the [A, a] range are reversed, which means that all 0 becomes 1, and all 1 becomes 0
3 A B asks how many of the total number of 1 in the [a, b] interval
4 A B queries the maximum number of consecutive 1 in the [a, b] interval
For each kind of inquiry operation, LXHGWW need to give the answer, intelligent program staff, you can help him?
Error log: More content and important, will be written below bold
Solution
Segment tree, you need to maintain the following information:
- The number of \ (sum\) interval \ (1\)
- \ ( 0/1\) longest contiguous sub-segment in \ (max[0/1]\) interval
- \ (lmax[0/1]\) contains interval left endpoint longest \ (0/1\) sub- segment
- \ (rmax[0/1]\) contains interval right endpoint longest \ (0/1\) sub- segment
In view of the interval operation, two more tokens are required:
- \ (lazy = {-1, 0, 1}\) is \ ( -1\) for stateless, \ (0/1\) indicates that the interval is all assigned to \ (0/1\)
- \ (rev = {0, 1}\) interval is flipped
Need to maintain more elements, first (pushup\)
Interval and direct addition can
There are two cases of contiguous sub-segments that contain left endpoints:
- Direct inheritance of the left interval \ (lmax\)
- When the left interval is full/full empty, the left end point can be crossed, plus the part of the right interval
Right interval update similarly
For the longest contiguous sub-segment of the interval, there are three cases
- Direct inheritance of larger values of the left interval
- Direct inheritance of larger values in the right interval
- The oldest part of the right end of the left interval and the right interval contain the oldest segment of the left endpoint, that is, the longest section spans the interval dividing line
The above needs to be divided into (0/1\) discussion, the process of direct two-tier loop to solve
And then to the difficulty \ (pushdown\)
I'm a player who needs to be on the provincial team until now, and that's a terrible thing to notice.
In the line tree \ (pushdown\) operation, we need to clarify two things:
- Priority of the tag
2. Whether a tag will be affected by another type tag on a child node
Here we focus on the 2nd (the 1th interval is definitely higher than the rollover, so the priority to split the interval assignment tag, when the tag is split to clear the flip mark)
When you disassemble a tag, we need to not only explicitly devolve this tag to the child nodes, but also how the same type of markup should be changed, and how this tag will be affected by the different types of tags .
Clearly the same type of effect is generally not a problem, such as the interval marked down, the sub-node of the interval plus the mark accumulated on this value
Take the case as an example:
when the interval assignment tag is disassembled, not only will the sub-interval assignment tag be updated to this value, but the child node rollover tag will also be emptied (although this seems to have little effect, the rollover mark will be emptied when the value tag is split)
When splitting the interval reversal tag, it is necessary to consider the effect of this marker pushing the sub-interval assignment tag and the rollover tag in two different cases.
Considering that the priority of an assignment tag is greater than the rollover tag, the assignment tag is flipped directly in the case of an assignment tag
The rest of the situation rollover mark XOR equals 1
While the rest of the code is long, it will have a deep understanding of the segment tree.
Such a complete consideration of all situations is the basic accomplishment of a \ (oi\) player
Well, that's it, \ (rng\) Don't be frustrated, you are the best; \ (s8\) ,\ (lpl\) refueling!
Code
#include <iostream> #include <cstdio> #include <queue> #include <cstring> #include < algorithm> #include <climits> #define LL long long#define REP (i, x, y) for (int i = (x); I <= (y); i++) using Namespa Ce std;int RD () {int out = 0,flag = 1;char c = GetChar (); while (C < ' 0 ' | | c > ' 9 ') {if (c = = '-') ' flag = -1;c = GetChar ();} while (c >= ' 0 ' && C <= ' 9 ') {off = out * + C-' 0 '; c = GetChar ();} return flag * out; }const int maxn = 200019;int num, na;int V[MAXN]; #define LID (ID << 1) #define RID (ID << 1) | 1//int Max (int a, int b) {return a > b a:b;} Heard handwriting fast? struct seg_tree{int L, R; int sum; int Lazy;//-1.null 0. All 0 1. all 1 int rev; int max[2], lmax[2], rmax[2]; }TREE[MAXN << 2];void pushup (int id) {tree[id].sum = tree[lid].sum + tree[rid].sum; REP (i, 0, 1) {tree[id].lmax[i] = Tree[lid].lmax[i]; if (i = = 1 && tree[lid].sum = = tree[lid].r-tree[lid].l + 1)//left zone full Tree[id].lmax[i] + = tree[rid].lmax[i];//can span else if (i = = 0 && Tree[lid].sum = = 0)//left zone full empty Tree[id].lmax[i] + = Tree[rid].lmax[i]; Tree[id].rmax[i] = Tree[rid].rmax[i]; if (i = = 1 && tree[rid].sum = = tree[rid].r-tree[rid].l + 1) tree[id].rmax[i] + + tree[lid].rmax[i]; else if (i = = 0 && Tree[rid].sum = = 0) tree[id].rmax[i] + = Tree[lid].rmax[i]; Tree[id].max[i] = Tree[lid].rmax[i] + tree[rid].lmax[i];//middle Tree[id].max[i] = max (Tree[id].max[i], tree[lid].max[i ]);//inheritance sub-interval tree[id].max[i] = max (Tree[id].max[i], tree[rid].max[i]); }}void build (int id, int l, int r) {tree[id].l = L, TREE[ID].R = r, Tree[id].lazy =-1; if (L = = r) {tree[id].sum = v[l]; Tree[id].max[0] = tree[id].lmax[0] = tree[id].rmax[0] = v[l] = = 0; TREE[ID].MAX[1] = tree[id].lmax[1] = tree[id].rmax[1] = v[l] = = 1; return; } int mid = (L + R) >> 1; Build (Lid, L, mid), build (RID, mid + 1, R); Pushup (ID); }void pushdown (int id) {if (Tree[id].lazy! =-1) {//priority highest Tree[id].rev = 0;//empty tag int val = Tree[id].lazy; Tree[lid].sum = (TREE[LID].R-TREE[LID].L + 1) * val; Tree[rid].sum = (TREE[RID].R-TREE[RID].L + 1) * val; Tree[lid].lazy = Tree[rid].lazy = val; Tree[lid].rev = Tree[rid].rev = 0; Tree[lid].max[val] = Tree[lid].lmax[val] = Tree[lid].rmax[val] = tree[lid].r-tree[lid].l + 1; Tree[lid].max[val ^ 1] = tree[lid].lmax[val ^ 1] = tree[lid].rmax[val ^ 1] = 0; Tree[rid].max[val] = Tree[rid].lmax[val] = Tree[rid].rmax[val] = tree[rid].r-tree[rid].l + 1 ; Tree[rid].max[val ^ 1] = tree[rid].lmax[val ^ 1] = tree[rid].rmax[val ^ 1] = 0; Tree[id].lazy =-1; } if (Tree[id].rev) {tree[lid].sum = (tree[Lid].r-tree[lid].l + 1)-tree[lid].sum; Tree[rid].sum = (TREE[RID].R-TREE[RID].L + 1)-tree[rid].sum; if (tree[lid].lazy! =-1) tree[lid].lazy ^= 1;//Synthetically considers the priority, the effect on other marks else Tree[lid].rev ^= 1; if (tree[rid].lazy! =-1) tree[rid].lazy ^= 1; else Tree[rid].rev ^= 1; Swap (tree[lid].max[0], tree[lid].max[1]); Swap (tree[lid].lmax[0], tree[lid].lmax[1]); Swap (tree[lid].rmax[0], tree[lid].rmax[1]); Swap (tree[rid].max[0], tree[rid].max[1]); Swap (tree[rid].lmax[0], tree[rid].lmax[1]); Swap (tree[rid].rmax[0], tree[rid].rmax[1]); Tree[id].rev = 0; }}void update (int id, int val, int l, int r) {pushdown (ID); if (TREE[ID].L = = L && TREE[ID].R = = r) {if (val = = 0 | | val = = 1) {tree[id].sum = (tree[id].r-t REE[ID].L + 1) * val; Tree[id].lazy = val; Tree[id].max[val] = Tree[id].lmax[val] = Tree[id].Rmax[val] = tree[id].r-tree[id].l + 1; Tree[id].max[val ^ 1] = tree[id].lmax[val ^ 1] = tree[id].rmax[val ^ 1] = 0; } else if (val = = 2) {Tree[id].sum = (TREE[ID].R-TREE[ID].L + 1)-tree[id].sum; Tree[id].rev ^= 1; Swap (tree[id].max[0], tree[id].max[1]); Swap (tree[id].lmax[0], tree[id].lmax[1]); Swap (tree[id].rmax[0], tree[id].rmax[1]); } return; } int mid = (tree[id].l + tree[id].r) >> 1; if (Mid < L) Update (RID, Val, L, R); else if (Mid >= R) Update (lid, Val, L, R); else update (lid, Val, L, Mid), update (RID, Val, mid + 1, R); Pushup (ID); }int query (int id, int l, int r) {pushdown (ID); if (TREE[ID].L = = L && TREE[ID].R = = r) return tree[id].sum; int mid = (tree[id].l + tree[id].r) >> 1; if (Mid < L) return query (RID, L, R); else if (Mid >= R) return query (lid, L, R); ELSE return query (LID, L, mid) + query (RID, mid + 1, R); }seg_tree Q_max (int id, int l, int r) {pushdown (ID); if (TREE[ID].L = = L && TREE[ID].R = = r) return Tree[id]; int mid = (tree[id].l + tree[id].r) >> 1; if (Mid < L) return Q_max (RID, L, R); else if (Mid >= R) return Q_max (lid, L, R); else{seg_tree ret, L = q_max (lid, L, mid), R = Q_max (RID, mid + 1, R); Ret.sum = L.sum + r.sum; REP (i, 0, 1) {ret.lmax[i] = L.lmax[i]; if (i = = 1 && l.sum = = L.R-L.L + 1)//left zone full full ret.lmax[i] + = r.lmax[i];//can span else if (i = = 0 && L.sum = = 0)//left zone full empty ret.lmax[i] + = R.lmax[i]; Ret.rmax[i] = R.rmax[i]; if (i = = 1 && r.sum = = r.r-r.l + 1) ret.rmax[i] + + l.rmax[i]; else if (i = = 0 && R.sum = = 0) ret.rmax[i] + = L.rmax[i]; Ret.max[i] = L.rmax[i] + r.lmax[i];//Middle Ret.max[i] = max (Ret.max[i], l.max[i]);//Inheritance Sub-range ret.max[i] = max (Ret.max[i], r.max[i]); } return ret; }}int Main () {num = rd (), na = rd (); REP (i, 1, num) v[i] = RD (); Build (1, 1, num); while (na--) {int cmd = RD (), L = Rd (), r = Rd (); l++, r++; if (cmd = = 0) Update (1, 0, L, R); else if (cmd = = 1) update (1, 1, L, R); else if (cmd = = 2) update (1, 2, L, R); else if (cmd = = 3) printf ("%d\n", Query (1, L, R)); else printf ("%d\n", Q_max (1, L, R). Max[1]); } return 0; }
P2572 [SCOI2010] sequence action