ACdream1157 Segments(CDQ分治 + 线段树)
题目这么说的:
进行如下3种类型操作:
1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]
2)C i (1-base) 删除第i条增加的线段,保证每条插入线段最多插入一次,且这次删除操作一定合法
3) Q L R(1 <= L <= R <= 1000000000) 查询目前存在的线段中有多少条线段完全包含[L,R]这个线段,线段X被线段Y完全包含即LY <= LX <= RX <= RY)
初学CDQ分治是看了Balkan OI 2007 Mokia那题的解法。两题类似,这题做法也不难想出:
- 每次对操作的区间进行分治时,统计左半边更新操作对右半边查询操作的影响,影响的前提是更新操作的L小于等于查询操作的L且R要大于等于查询的R,这个通过一开始把L按从小到大排序,分治时便可从大到小遍历,同时用线段树维护R出现次数即可。
其实我一开始看错题,以为询问的是有几条线段包含在给定区间里面,写完后发现才样例过不了。。不过改一下就好了,然后1A感觉还是不错的。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int tree[222222<<2],N,x,y; 7 void update(int i,int j,int k){ 8 if(i==j){ 9 tree[k]+=y; 10 return; 11 } 12 int mid=i+j>>1; 13 if(x<=mid) update(i,mid,k<<1); 14 else update(mid+1,j,k<<1|1); 15 tree[k]=tree[k<<1]+tree[k<<1|1]; 16 } 17 int query(int i,int j,int k){ 18 if(x<=i && j<=y){ 19 return tree[k]; 20 } 21 int mid=i+j>>1,res=0; 22 if(x<=mid) res+=query(i,mid,k<<1); 23 if(y>mid) res+=query(mid+1,j,k<<1|1); 24 return res; 25 } 26 27 struct Query{ 28 int idx,type,anspos; 29 int x,y; 30 bool operator<(const Query &q)const{ 31 return x<q.x; 32 } 33 }que[111111],tmp[111111]; 34 35 int ans[111111]; 36 37 void cdq(int l,int r){ 38 if(l>=r) return; 39 int mid=l+r>>1,i=l,j=mid+1; 40 for(int k=l; k<=r; ++k){ 41 if(que[k].idx<=mid) tmp[i++]=que[k]; 42 else tmp[j++]=que[k]; 43 } 44 for(int k=l; k<=r; ++k) que[k]=tmp[k]; 45 46 for(i=mid+1,j=l; i<=r; ++i){ 47 if(que[i].type!=3) continue; 48 for( ; j<=mid && que[j].x<=que[i].x; ++j){ 49 if(que[j].type==3) continue; 50 x=que[j].y; y=(que[j].type==1) ? 1 : -1; 51 update(0,N-1,1); 52 } 53 x=que[i].y; y=N-1; 54 ans[que[i].anspos]+=query(0,N-1,1); 55 } 56 for(i=l; i<j; ++i){ 57 if(que[i].type==3) continue; 58 x=que[i].y; y=(que[i].type==1) ? -1 : 1; 59 update(0,N-1,1); 60 } 61 cdq(l,mid); cdq(mid+1,r); 62 } 63 64 int segx[111111],segy[111111],sn; 65 int point[222222],pn; 66 int main(){ 67 char op; 68 int n,a,b; 69 while(~scanf("%d",&n)){ 70 int cnt=0; 71 memset(ans,0,sizeof(ans)); 72 sn=0; pn=0; 73 for(int i=0; i<n; ++i){ 74 scanf(" %c",&op); 75 if(op=='D'){ 76 scanf("%d%d",&a,&b); 77 segx[++sn]=a; segy[sn]=b; 78 point[pn++]=a; point[pn++]=b; 79 que[i].idx=i; que[i].type=1; que[i].x=a; que[i].y=b; 80 }else if(op=='C'){ 81 scanf("%d",&a); 82 que[i].idx=i; que[i].type=2; que[i].x=segx[a]; que[i].y=segy[a]; 83 }else{ 84 scanf("%d%d",&a,&b); 85 point[pn++]=a; point[pn++]=b; 86 que[i].idx=i; que[i].type=3; que[i].x=a; que[i].y=b; que[i].anspos=++cnt; 87 } 88 } 89 90 sort(point,point+pn); 91 pn=unique(point,point+pn)-point; 92 for(N=1; N<pn; N<<=1); 93 94 for(int i=0; i<n; ++i){ 95 que[i].x=lower_bound(point,point+pn,que[i].x)-point; 96 que[i].y=lower_bound(point,point+pn,que[i].y)-point; 97 } 98 99 sort(que,que+n); 100 cdq(0,n-1); 101 102 for(int i=1; i<=cnt; ++i){ 103 printf("%d\n",ans[i]); 104 } 105 } 106 return 0; 107 }