Acdream1157---Segments (CDQ分治)
生活随笔
收集整理的這篇文章主要介紹了
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 }?
轉載于:https://www.cnblogs.com/oneshot/p/4143950.html
總結
以上是生活随笔為你收集整理的Acdream1157---Segments (CDQ分治)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java自定义Exception
- 下一篇: 【转】oracle sequence