ACdream 1157 (cdq分治)
Segments
Time Limit: 4000/2000MS (Java/Others)Memory Limit: 20000/10000KB (Java/Others)Problem Description
由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种类型之一Input
多组数据,每组数据N
接下来N行,每行是三种操作之一(1 <= N <= 10^5)
Output
对于每个Q操作,输出一行,答案Sample Input
6 D 1 100 D 3 8 D 4 10 Q 3 8 C 1 Q 3 8
Sample Output
2 1
Hint
注意,删除第i条增加的线段,不是说第i行,而是说第i次增加。
比如
D 1 10
Q 1 10
D 2 3
D 3 4
Q 5 6
D 5 6
C 2是删除D 2 3
C 4是删除D 5 6
第一次听说cdq分治,cdq是陈丹琦orz。。
在我们平常使用的分治中,每一个子问题只解决它本身(可以说是封闭的)。
而在cdq分治中,对于划分出来的两个子问题,前一个子问题用来解决后一个子问题而不是它本身。
具体算法流程如下:
1.将整个操作序列分为两个长度相等的部分(分)
2.递归处理前一部分的子问题(治1)
3.计算前一部分的子问题中的修改操作对后一部分子问题的影响(治2)
4.递归处理后一部分子问题(治3)
另外,能使用常量引用的地方尽量使用,可以提高效率。
Accepted Code:
1 /*************************************************************************
2 > File Name: 1157.cpp
3 > Author: Stomach_ache
4 > Mail: sudaweitong@gmail.com
5 > Created Time: 2014年08月10日 星期日 08时24分10秒
6 > Propose:
7 ************************************************************************/
8
9 #include <cmath>
10 #include <string>
11 #include <cstdio>
12 #include <vector>
13 #include <fstream>
14 #include <cstring>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18
19 const int maxn = 100055;
20 int c[maxn<<1], l[maxn], r[maxn], ans[maxn];
21 struct node {
22 int t, id, l, r;
23 node() {}
24 node(int a, int b, int c, int d) {
25 t = a; id = b; l = c; r = d;
26 }
27 }a[maxn];
28 vector<int> xs;
29 int w;
30
31 bool cmp1(const node &a, const node &b) {
32 return a.id < b.id;
33 }
34
35 bool cmp2(const node &a, const node &b) {
36 if (a.l != b.l) return a.l < b.l;
37 return a.r > b.r;
38 }
39
40 int lowbit(int x) {
41 return x & -x;
42 }
43
44 void add(int x, int v) {
45 x = 2*maxn - x;
46 while (x < maxn*2) {
47 c[x] += v;
48 x += lowbit(x);
49 }
50 }
51
52 int sum(int x) {
53 int res = 0;
54 x = 2*maxn - x;
55 while (x > 0) {
56 res += c[x];
57 x -= lowbit(x);
58 }
59 return res;
60 }
61
62 void solve(int l, int r) {
63 if (l >= r) return ;
64 int mid = (l + r) >> 1;
65 solve(l, mid);
66 sort(a+l, a+r+1, cmp2);
67 for (int i = l; i <= r; i++) {
68 if (a[i].id <= mid) {
69 if (a[i].t == 1) add(a[i].r, 1);
70 else if (a[i].t == -1) add(a[i].r, -1);
71 } else {
72 if (a[i].t == 0) ans[a[i].id] += sum(a[i].r);
73 }
74 }
75 for (int i = l; i <= r; i++) if (a[i].id <= mid) {
76 if (a[i].t == 1) add(a[i].r, -1);
77 if (a[i].t == -1) add(a[i].r, 1);
78 }
79 sort(a+l, a+r+1, cmp1);
80 solve(mid+1, r);
81 }
82
83 int main(void) {
84 int n;
85 while (~scanf("%d", &n)) {
86 int cnt = 1;
87 xs.clear();
88 for (int i = 1; i <= n; i++) {
89 char s[10];
90 scanf("%s", s);
91 if (s[0] == 'D') {
92 int x, y;
93 scanf("%d %d", &x, &y);
94 xs.push_back(x);
95 xs.push_back(y);
96 l[cnt] = x;
97 r[cnt++] = y;
98 a[i] = node(1, i, x, y);
99 } else if (s[0] == 'Q') {
100 int x, y;
101 scanf("%d %d", &x, &y);
102 xs.push_back(x);
103 xs.push_back(y);
104 a[i] = node(0, i, x, y);
105 } else {
106 int id;
107 scanf("%d", &id);
108 a[i] = node(-1, i, l[id], r[id]);
109 }
110 }
111 sort(xs.begin(), xs.end());
112 xs.erase(unique(xs.begin(), xs.end()), xs.end());
113 w = xs.size();
114 for (int i = 1; i <= n; i++) {
115 a[i].l = lower_bound(xs.begin(), xs.end(), a[i].l)-xs.begin()+1;
116 a[i].r = lower_bound(xs.begin(), xs.end(), a[i].r)-xs.begin()+1;
117 //printf("%d %d\n", a[i].l, a[i].r);
118 }
119 //memset(c, 0, sizeof(c));
120 memset(ans, 0, sizeof(ans));
121 solve(1, n);
122 for (int i = 1; i <= n; i++) if (!a[i].t) printf("%d\n", ans[i]);
123 }
124 return 0;
125 }
posted on 2014-08-10 10:57 Stomach_ache 阅读(1087) 评论(0) 编辑 收藏 举报