Test instructions: An array of 0~n-1, with an initial value of 0, and the number of segments of a contiguous segment with a current value of 0 executed after each operation.
Operation 1:p I j:i~j the value of each element of the interval minus 1
Operation 2:r I j:i~j interval of each element value plus 1, each r operation, there must be a corresponding P operation
Data range: 1 <= n <= 108, 0 <= m <= 20000
Line tree now has become the basic skills of competitors, but I this piece is weak, write down this puzzle, to facilitate their review later.
Analysis, which is obviously a problem solved by line-segment tree, but the data range is too large. Note that the maximum number of operations is only 20,000 times, assuming that all operations are executed, and that many of the array elements are actually "fragment"--marking the two endpoint positions of all operations, then the element values between the two adjacent marker points (not including the endpoints) are always the same, so they are shrunk to a point, This simplifies the problem, and the data range is about n < 60100 and can be solved with a segment tree.
Puzzle: The node of the segment tree is defined as follows:
struct node{ int cnt, h; h = "Interval" Height bool LF, RF; mark the leftand right endpoint is equal to 0}nd[n<<2];
Nodes should have a left and right end point, in order to save memory is not written, write the function when the endpoint as a parameter passed on it (see Code).
CNT represents the number of consecutive segments with a current segment value of 0, and LF and RF respectively mark whether the value of the left and right endpoints of the corresponding interval of the current node is equal to the 0;h is the height of the whole operation of the segment, in fact, the H is the maximum height of the interval, because the R operation must correspond to a previous p operation, , then it is impossible to have the H of the sub-node is larger than the h of the current node, so h is the maximum value of the interval. This is a very important inference, when the query to a certain interval, if its H value is not 0, there is no need to look down, because it is impossible to find the solution, conversely, if the node's H value is 0, then the whole paragraph does not have any action, in other words, the sub-node has no effect, Then you can update the value of the current node with the value of the child node.
The code is as follows:
#include <cstdio>#include<algorithm>using namespacestd;#defineN 41000#defineLC (ID<<1)#defineRC (id<<1|1)structnode{intCNT, H;//h = "interval height" BOOLLF, RF;//mark the left and right endpoint is equal to 0} nd[n<<2];voidBuildintLintRintID) {ND[ID].LF= ND[ID].RF =true; Nd[id].cnt=1; Nd[id].h=0; if(L = = r)return; intMID = L+r>>1; Build (L, Mid, LC); Build (Mid+1, R, RC);}voidPushup (intIdintLintR) { if(Nd[id].h! =0)//according to the title description, at this time this paragraph certainly does not have a height of 0 points{//the R operation must be a P operation before canceling. So, nd[id].h equivalent to the highest height of the paragraphnd[id].cnt =0; ND[ID].LF= ND[ID].RF =false; return; } if(L = =R) {nd[id].cnt=1; ND[ID].LF= ND[ID].RF =true; return; } Else{//note or nd[id].h==0, that at this time, the whole is equivalent to no operation, according to the child node with the new node value can beND[ID].LF = nd[lc].lf, Nd[id].rf =Nd[rc].rf; Nd[id].cnt= nd[lc].cnt + nd[rc].cnt-(Nd[lc].rf &&ND[RC].LF); }}voidAddintLintRintVintLintRintID) { intMID = L+r>>1; if(l <= l && R >=R) {nd[id].h+=v; Pushup (ID, L, R); return; } if(L <=mid) Add (L, R, V, L, Mid, LC); if(R > Mid) Add (L, R, V, mid+1, R, RC); Pushup (ID, L, R);}//-------------------structquery{Charop[3]; intL, R;} Qry[n>>1];intX[n];intxcnt;//-------------------intMain () {intT, N, Q; CharTM; intL, R; scanf ("%d", &T); for(intCAS =1; CAS <= T; cas++) {scanf ("%d%d", &n, &q); Xcnt=0; X[xcnt++] =0; X[xcnt+ +] = N1; inti; for(i =0; i < Q; i++) {scanf ("%s%d%d", Qry[i].op, &l, &R); QRY[I].L= L, QRY[I].R =R; X[xcnt++] =l; X[xcnt++] =R; } sort (x, x+xcnt); Xcnt= Unique (x, x+xcnt)-x; for(i = xcnt-1; i >0; i--)if(X[i]! = x[i-1]+1) x[xcnt++] = x[i-1]+1; /*Do not do the inverse example 5 2 P 0 1 P 3 4*/sort (x, x+xcnt); Build (0, xcnt-1,1); printf ("Case #%d:\n", CAs); for(i =0; i < Q; i++) {L= Lower_bound (x, x+xcnt, QRY[I].L)-x; R= Lower_bound (x, x+xcnt, QRY[I].R)-x; Add (L, R, qry[i].op[0] =='P'? -1:1,0, xcnt-1,1); printf ("%d\n", nd[1].cnt); } } return 0;}
Zoj 3325 Machine (segment tree)