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)
给出N,接下来N行,每行是3种类型之一
由于 L R 比较大,直接是不行的,于是我们可以利用CDQ分治把二维变成一维,然后离散化。树状数组查询。
对于询问 L R 只需要 知道 小于等于L 且大于等于R的有多少个就可以了。这里我是把线段左端点进行CDQ分治,然后每次查询大于R数目。
1 #include <cstdio> 2 #include <string> 3 #include <vector> 4 #include <cstdlib> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 const int maxn = 1e5+10; 10 struct Node 11 { 12 int idx,l,r,delt; 13 int kind; 14 bool operator < (const Node &rhs)const 15 { 16 return l < rhs.l ; 17 } 18 }node[maxn]; 19 int ans[maxn],del[maxn]; 20 //-------------BIT--------- //此处树状数组反向写的,用于查询 大于等于x的数有多少个 21 inline int lowbit (int x) 22 { 23 return x & -x; 24 } 25 int arr[maxn],MAX; 26 void add (int x,int d) 27 { 28 while (x) 29 { 30 arr[x] += d; 31 x -= lowbit(x); 32 } 33 } 34 int sum(int x) 35 { 36 int ans = 0; 37 while (x <= MAX) 38 { 39 ans += arr[x]; 40 x += lowbit(x); 41 } 42 return ans; 43 } 44 //--------------离散化----- 45 int vec[maxn],vec_idx; 46 int hash_(int x) 47 { 48 return lower_bound(vec,vec+vec_idx,x) - vec + 1; 49 } 50 //------------------------ 51 void CDQ(int l,int r) 52 { 53 if (l == r) 54 return; 55 int mid = (l + r) >> 1; 56 CDQ(l,mid); 57 CDQ(mid+1,r); 58 int j = l; 59 for (int i = mid+1; i <= r; i++) 60 { 61 if (node[i].kind == 2) 62 { 63 for ( ;j <= mid && node[j].l <= node[i].l; j++) 64 { 65 if (node[j].kind == 1) 66 { 67 add(hash_(node[j].r),node[j].delt); 68 } 69 } 70 ans[node[i].idx] += sum(hash_(node[i].r)); 71 } 72 } 73 for (int i = l; i < j; i++) 74 if ( node[i].kind == 1) 75 add(hash_(node[i].r),-node[i].delt); 76 inplace_merge(node+l,node+mid+1,node+r+1); 77 } 78 int vis[maxn]; 79 int main(void) 80 { 81 #ifndef ONLINE_JUDGE 82 freopen("in.txt","r",stdin); 83 #endif 84 int n; 85 while (~scanf ("%d",&n)) 86 { 87 int cnt = 0; 88 vec_idx = 0; 89 memset(arr,0,sizeof(arr)); 90 memset(ans,0,sizeof(ans)); 91 memset(vis,0,sizeof(vis)); 92 vector<int>vv; 93 for (int i = 1; i <= n; i++) 94 { 95 char op[3]; 96 scanf ("%s",op); 97 if (op[0] == 'D') 98 { 99 scanf ("%d%d",&node[i].l,&node[i].r); 100 node[i].kind = 1; 101 node[i].idx = i; 102 node[i].delt = 1; 103 vec[vec_idx++] = node[i].r; 104 vv.push_back(i); 105 } 106 if (op[0] == 'Q') 107 { 108 scanf ("%d%d",&node[i].l,&node[i].r); 109 node[i].kind = 2; 110 node[i].idx = i; 111 vec[vec_idx++] = node[i].r; 112 vis[i] = 1; 113 } 114 if (op[0] == 'C') 115 { 116 int tmp; 117 scanf ("%d",&tmp); 118 node[i].kind = 1; 119 node[i].l = node[vv[tmp-1]].l; 120 node[i].r = node[vv[tmp-1]].r; 121 node[i].delt = -1; // 对于删除的边类型与增加的相同但是,操作的时候是-1 122 node[i].idx = i; 123 } 124 } 125 sort(vec,vec+vec_idx); 126 vec_idx = unique(vec,vec+vec_idx) - vec; 127 MAX = vec_idx + 10; 128 CDQ(1,n); 129 for (int i = 1; i <= n; i++) 130 { 131 if (vis[i]) 132 printf("%d\n",ans[i]); 133 } 134 } 135 return 0; 136 }