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: [email protected]  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 }

 

你可能感兴趣的:(cd)