Http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html
With the line segment tree, first of all to define the node information of the line segment tree, generally see a problem, it is difficult to quickly determine the segment tree to record information
To do the line tree is not to do the problem, the first line tree is an auxiliary structure, it is for the problem, and therefore must be specific problems specific analysis
Recall the RMQ problem, in fact, solve RMQ there are many ways, do not need to use the line segment tree, with the line segment tree to solve the RMQ, in fact, the use of the nature of the segment tree to help solve the problem
Recall the problem of the rectangular area and or perimeter, the general use of the scanning line method, in fact, the scanning line method and the line segment tree has no relationship, the scanning line method should be classified as the computational geometry of the algorithm,
Line tree is used only to assist in the implementation of the scan line method
So back to this question, to solve, must analyze the nature of the problem, just to think how to use line tree to assist, and why the use of line tree support is feasible, this problem seems more valuable
1 query operation, find a length of W's not covered by the leftmost interval
2 Update operation to empty a contiguous area
Update operation is relatively easy to solve, the key is how to implement the query operation
Since it is to find a length of at least a range of W, to achieve this, it is not difficult, we can add a domain Tlen in each node of the segment tree, indicating the maximum length of the interval available for the interval,
As for the specific position of this tlen interval, it is only known that there is such an interval within the interval, and note that this tlen represents the maximum length, the node may have multiple segments available, but the longest length is Tlen
By recording this information, you can at least solve the problem of finding a suitable interval. If the interval length of the query is W > the tlen of the total interval, then the query must be unsuccessful (the maximum interval in the total interval can not be satisfied that must fail)
But this is not enough, one query is to return the specific location of the interval, where the location can not be returned, the other is to query the leftmost interval, the leftmost and satisfy the >=w interval may not be this tlen interval
So let's think about this further.
First, we'll add two domains, Llen,rlen
Llen represents the maximum length of a range that is available from the leftmost end
For example, the interval [1,5], the coverage is [0,0,0,1,1],llen = 3, from the leftmost side of the 3 can be exploited
interval [1,5], coverage = [1,0,0,0,0],llen = 0, since the left-most start can not find a range of 1 cells available
Rlen represents the maximum length of a range that is available from the right-most
For example, the interval [1,5], the coverage is [1,0,1,0,0],rlen = 2, from the right side of the 2 can be exploited
interval [1,5], coverage = [0,0,0,0,1],rlen = 0, because no more than 1 compartments are available from the right-most start
For an interval, we know that the left half of the Tlen, and the right half of the interval of Tlen, if the left half of the Tlen >= W, then we can be found on the left (to satisfy the leftmost), so you can go deep into the left half to determine the specific location of the interval
If the left side is not satisfied, then we have to consider the interval across the two sides (because to meet the leftmost), so the recorded Llen,rlen can come in handy, a span of interval,
Then the left interval Rrlen + right interval llen, if satisfied, is the interval, and its position can be determined
If the span is not satisfied, then in the right half of the interval to find, if the right half of the Tlen >= W, then can be found in the right half of the interval, so deep into the right half to determine its specific location, otherwise, the entire query failed
Visible query is based on Tlen,llen,rlen this information, and each query is actually accompanied by the modification, and there are special modifications, these changes will change the value of Tlen,llen,rlen, so in the update is always maintain the information
About the maintenance of these 3 information
Tlen of current interval = max{left half interval tlen, right half interval tlen, left half interval rlen+ right half Llen} (this is not difficult to understand, take the larger one, or across the middle one)
If the left half of the range can be used: the current interval Llen = left half interval llen (Tlen) + right half of the interval Llen
The left half interval part can be used: the current interval Llen = The left half interval llen
If the right half of the range can be used: current interval Rlen = right half interval Rlen (Tlen) + left half interval rlen
The right half section can be used: current interval Rlen = right half interval rlen
This will all be maintained.
The idea is actually simple:
and normal segment tree interval update is not necessarily the place, he does not give the range of the tail, but to find a continuous interval update. The length is also given, so all we have to do is find his head node.
If we have the longest and longest consecutive left of each node, we can find this head node, and see the code in detail.
#include <iostream>#include<string>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>#include<stack>#include<queue>#include<cctype>#include<vector>#include<iterator>#include<Set>#include<map>#include<sstream>using namespacestd;#defineMem (A, B) memset (A,b,sizeof (a))#definePF printf#defineSF scanf#defineSPF sprintf#definePB Push_back#defineDebug printf ("!\n")#defineMAXN 65535*2#defineMAX (A, b) a>b?a:b#defineBlank pf ("\ n")#defineLL Long Long#defineAll (x) X.begin (), X.end ()#defineINS (x) Inserter (X,x.begin ())#definePqueue priority_queue#defineINF 0x3f3f3f3f#defineLS (rt<<1)#defineRS (rt<<1|1)intn,m;inta[maxn<<3],col[maxn<<3],lsum[maxn<<3],rsum[maxn<<3],ans;voidBuildintLintRintRT) {A[rt]= Lsum[rt] = Rsum[rt] = r-l+1; COL[RT]= -1; if(L==R)return; intMid = (l+r) >>1; Build (L,mid,ls); Build (Mid+1, R,rs);}voidPushdown (intRtintk) { if(col[rt]!=-1) {Col[ls]= Col[rs] =Col[rt]; LSUM[LS]= Rsum[ls] = A[ls] = Col[rt]?0:(K (k>>1)); LSUM[RS]= Rsum[rs] = A[rs] = Col[rt]?0:(k>>1); COL[RT]= -1; }}voidPushup (intRtintk) {Lsum[rt]=Lsum[ls]; RSUM[RT]=Rsum[rs]; if(Lsum[rt] = = K (k>>1)) lsum[rt]+=Lsum[rs]; if(Rsum[rt] = = k>>1) rsum[rt]+=Rsum[ls]; A[RT]= Max (Rsum[ls] +Lsum[rs],max (A[ls],a[rs]));}voidUpdateintValintLintRintLintRintRT) { if(l <= l && R <=R) {A[rt]= Lsum[rt] = Rsum[rt] = val?0: r-l+1; COL[RT]=Val; return; } pushdown (Rt,r-l+1); intMid = (l+r) >>1; if(L <=mid) Update (VAL,L,R,L,MID,LS); if(R > Mid) Update (val,l,r,mid+1, R,rs); Pushup (Rt,r-l+1);}intQueryintCintLintRintRT) { if(L==R)return 1; Pushdown (Rt,r-l+1); intMid = (l+r) >>1; if(A[LS]>=C)returnquery (C,L,MID,LS); Else if(Rsum[ls]+lsum[rs] >= c)returnMID-RSUM[LS] +1; Else returnQuery (c,mid+1, R,rs);}intMain () {inti,j; while(~SF ("%d%d",&n,&m) {Build (1N1); for(i=0; i<m;i++) { inttmp,c,d; SF ("%d",&tmp); if(tmp==1) {SF ("%d",&c); if(a[1]<C) PF ("0\n"); Else { intv = query (c,1N1); PF ("%d\n", V); Update (1, v,v+c-1,1N1); } } Else{SF ("%d%d",&c,&d); Update (0, c,c+d-1,1N1); } } } return 0;}
POJ 3667 Segment Tree interval merging