Topic Link: Click to open the link
Test instructions: There are 3 kinds of interval operations, all of which turn a range into 1, a range of 0, a range of 1 into 0, 0 to 1.
Idea: The first two operations is the most basic interval update, using the lazy tag, however, the 3rd operation is a bit of trouble, if only update the current node corresponding to the large interval, then it contains a small interval is updated when the error occurs, the cause of the error is because of the overlap and collision of the tag. Obviously, this is a typical problem, dealing with the problem of tag collisions.
The core of the problem is resolving collisions so that each point has at most one marker at a time.
So what do we do? We can take a look at the equivalent of what happens when two markers collide:
When we want to update a node o:
If we are going to update the interval, we will overwrite it without having to control the original tag. But if the interval is reversed:
If the node already has a Mark V
So:
When v = = 1, indicating that the interval was once all changed to 1 of the operation, equivalent to this time all become 0, so the lazy mark eventually becomes 0.
When v = = 0, in the same vein, the lazy sign eventually becomes 1.
When the V = = 2, indicating that the interval has a full reversal of the operation has not been implemented, equivalent to this time not reversed, so the lazy mark eventually becomes-1
When v = =-1, indicating that there is no operation on the interval, equivalent to the need for reversal, the lazy mark eventually 2
In fact, it is an equivalent conversion, when more collisions will involve a processing of the shun-seeking problem.
Also, if you update the SUM[V when updating node V, then it involves the update of sum[v] in the equivalent conversion, so don't think wrong.
See the code for details:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include < string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include < cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue># Define MAX (a) > (b)? ( A):(B) #define MIN (a) < (b) ( A):(B)) using namespace Std;typedef long Long ll;const double PI = ACOs ( -1.0); const double EPS = 1e-6;const int mod = 10000 00000 + 7;const int INF = 1000000000;const int MAXN = 1024010;int t,n,m,q,l,r,kase=0,sum[maxn<<2],setv[maxn<< 2],a[maxn],cnt = 0;void pushup (int o) {Sum[o] = sum[o<<1] + sum[o<<1|1];} void pushdown (int l, int r, int o) {if (Setv[o]! =-1) {int m = (L + r) >> 1; if (setv[o] = = 1) {sum[o<<1] = (m-l + 1); SUM[O<<1|1] = (r-m); SETV[O<<1] = setv[o<<1|1] = Setv[o]; } else if (setv[o] = = 0) {sum[o<<1] = 0; Sum[o<<1|1] = 0; SETV[O<<1] = setv[o<<1|1] = Setv[o]; } else {if (setv[o<<1] = = 1) {setv[o<<1] = 0; Sum[o<<1] = 0; } else if (setv[o<<1] = = 0) {setv[o<<1] = 1; SUM[O<<1] = (m-l + 1); } else if (setv[o<<1] = = 2) setv[o<<1] = 1, sum[o<<1] = m-l + 1-sum[o<<1]; else {setv[o<<1] = 2; SUM[O<<1] = m-l + 1-sum[o<<1]; } if (setv[o<<1|1] = = 1) {setv[o<<1|1] = 0; Sum[o<<1|1] = 0; } else if (setv[o<<1|1] = = 0) {setv[o<<1|1] = 1; SUM[O<<1|1] = (r-m); } else if (setv[o<<1|1] = = 2)SETV[O<<1|1] = 1, sum[o<<1|1] = r-m-sum[o<<1|1]; else {setv[o<<1|1] = 2; SUM[O<<1|1] = r-m-sum[o<<1|1]; }} Setv[o] =-1; }}void Build (int l, int r, int o) {int m = (L + r) >> 1; Setv[o] =-1; if (L = = r) {++cnt; if (a[cnt]) sum[o] = 1; else Sum[o] = 0; return; } build (L, M, o<<1); Build (M+1, R, O<<1|1); Pushup (o);} void Update (int l, int r, int v, int l, int r, int o) {int m = (L + R) >> 1; if (l <= l && R <= R) {if (v = = 1) {Sum[o] = (r-l + 1); Setv[o] = 1; } else if (v = = 0) {Sum[o] = 0; Setv[o] = 0; } else {if (setv[o] = = 1) {Setv[o] = 0; Sum[o] = 0; } else if (setv[o] = = 0) {Setv[o] = 1; Sum[o] = r-l + 1; } else if (setv[o] = = 1) {Setv[o] = 2; Sum[o] = r-l + 1-sum[o]; } else Setv[o] =-1, Sum[o] = r-l + 1-sum[o]; } return; } pushdown (L, R, O); if (l <= m) update (L, R, V, L, M, o<<1); if (M < R) Update (L, R, V, M+1, R, O<<1|1); Pushup (o);} int query (int l, int r, int l, int r, int o) {int m = (L + R) >> 1; if (l <= l && R <= R) {return sum[o]; } pushdown (L, R, O); int ans = 0; if (l <= m) ans + = query (l, R, L, M, o<<1); if (M < r) ans + = query (L, R, M+1, R, O<<1|1); Pushup (o); return ans;} Char S[100];int main () {scanf ("%d", &t); while (t--) {scanf ("%d", &m); int n = 0; for (int i=0;i<m;i++) {scanf ("%d%s", &cnt,s); int len = strlen (s); while (cnt--) {for (int j=0;j<len;j++) {A[++n] = s[j]-' 0 '; }}} cnt = 0; Build (1, N, 1); scanf ("%d", &q); printf ("Case%d:\n", ++kase); int cc = 0; while (q--) {scanf ("%s%d%d", S,&l,&r); l++; r++; if (s[0] = = ' F ') update (L, R, 1, 1, N, 1); else if (s[0] = = ' E ') update (L, r, 0, 1, N, 1); else if (s[0] = = ' I ') update (L, R, 2, 1, N, 1); else printf ("q%d:%d\n", ++CC, Query (L, R, 1, N, 1)); }} return 0;}
11402-ahoy, pirates! (segment Tree interval update (labeling overlapping processing))