The title says:
The following 3 types of operations are performed:
1) D l R (1 <= l <= R <= 1000000000) Add a line segment [L,r]
2) C I (1-base) Delete the added segment of article I, to ensure that each insert segment is inserted at most once, and this delete operation must be legal
3) Q L R (1 <= l <= r <= 1000000000) query How many segments in the currently existing line segment fully contain [L,r] This segment, segment x is fully contained by Segment Y i.e. ly <= LX <= RX <= RY)
Beginner CDQ Division is to see Balkan OI Mokia The solution of the problem. Similar to the two questions, the practice is not difficult to think of:
- Each time the operation of the interval to divide, statistics left half of the update operation on the right side of the query operation, the premise is that the update operation of L is less than or equal to the query operation of the R and R to be greater than or equal to the query, this through the beginning of the L by small to large sort, divide and conquer can be from large to The number of R occurrences can also be maintained with the segment tree.
In fact, I began to look at the wrong question, thinking that the question is that there are a few line segments contained within a given interval, after the completion of the sample can not be found after the example. But it would be nice to change it, then 1 a feels good.
1#include <cstdio>2#include <cstring>3#include <algorithm>4 using namespacestd;5 6 inttree[222222<<2],n,x,y;7 voidUpdateintIintJintk) {8 if(i==j) {9tree[k]+=y;Ten return; One } A intMid=i+j>>1; - if(x<=mid) Update (i,mid,k<<1); - ElseUpdate (mid+1,j,k<<1|1); thetree[k]=tree[k<<1]+tree[k<<1|1]; - } - intQueryintIintJintk) { - if(X<=i && j<=y) { + returnTree[k]; - } + intMid=i+j>>1, res=0; A if(X<=mid) Res+=query (i,mid,k<<1); at if(Y>mid) Res+=query (mid+1,j,k<<1|1); - returnRes; - } - - structquery{ - intIdx,type,anspos; in intx, y; - BOOL operator< (ConstQuery &q)Const{ to returnx<q.x; + } -}que[111111],tmp[111111]; the * intans[111111]; $ Panax Notoginseng voidCdqintLintR) { - if(L>=R)return; the intMid=l+r>>1, i=l,j=mid+1; + for(intK=l; k<=r; ++k) { A if(Que[k].idx<=mid) tmp[i++]=Que[k]; the Elsetmp[j++]=Que[k]; + } - for(intK=l; k<=r; ++K) que[k]=Tmp[k]; $ $ for(i=mid+1, J=l; i<=r; ++i) { - if(que[i].type!=3)Continue; - for(; J<=mid && que[j].x<=que[i].x; + +)j) { the if(que[j].type==3)Continue; -X=QUE[J].Y; Y= (que[j].type==1) ?1: -1;WuyiUpdate0, N-1,1); the } -X=QUE[I].Y; y=n-1; WuAns[que[i].anspos]+=query (0, N-1,1); - } About for(i=l; i<j; + +)i) { $ if(que[i].type==3)Continue; -X=QUE[I].Y; Y= (que[i].type==1) ? -1:1; -Update0, N-1,1); - } ACDQ (L,mid); CDQ (mid+1, R); + } the - intsegx[111111],segy[111111],sn; $ intpoint[222222],PN; the intMain () { the Charop; the intn,a,b; the while(~SCANF ("%d",&N)) { - intCnt=0; inmemset (ans,0,sizeof(ans)); thesn=0; pn=0; the for(intI=0; i<n; ++i) { Aboutscanf"%c",&op); the if(op=='D'){ thescanf"%d%d",&a,&b); theSegx[++sn]=a; segy[sn]=b; +Point[pn++]=a; point[pn++]=b; -Que[i].idx=i; Que[i].type=1; Que[i].x=a; que[i].y=b; the}Else if(op=='C'){Bayiscanf"%d",&a); theQue[i].idx=i; Que[i].type=2; Que[i].x=segx[a]; que[i].y=Segy[a]; the}Else{ -scanf"%d%d",&a,&b); -Point[pn++]=a; point[pn++]=b; theQue[i].idx=i; Que[i].type=3; Que[i].x=a; Que[i].y=b; que[i].anspos=++CNT; the } the } the -Sort (point,point+PN); thePn=unique (POINT,POINT+PN)-Point ; the for(n=1; n<pn; n<<=1); the 94 for(intI=0; i<n; ++i) { theQue[i].x=lower_bound (point,point+pn,que[i].x)-Point ; theQue[i].y=lower_bound (POINT,POINT+PN,QUE[I].Y)-Point ; the }98 AboutSort (que,que+n); -Cdq0, N-1);101 102 for(intI=1; i<=cnt; ++i) {103printf"%d\n", Ans[i]);104 } the }106 return 0;107}
ACdream1157 Segments (CDQ Division + line Tree)