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
", 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
", ans[i]);
123     }
124     return 0;
125 }
原文地址:https://www.cnblogs.com/Stomach-ache/p/3902517.html