ACdream 1157 Segments(CDQ分治)

题目链接:http://acdream.info/problem?pid=1157

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操作,输出一行,答案

题目大意:略。

思路:传说这个就叫做CDQ分治,我也不确定是不是。对每一段[l..r],分治处理[l, mid]和[mid + 1..r]。对于[l..r],处理[l..mid]中的线段对[mid + 1..r]的影响,用树状数组处理一下就可以了。

代码(1608MS):

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <cstdio>
  5 using namespace std;
  6
  7 const int MAXN = 200010;
  8
  9 int hashmap[MAXN], hcnt;
 10 int tree[MAXN];
 11
 12 int hash(int x) {
 13     return lower_bound(hashmap, hashmap + hcnt, x) - hashmap + 1;
 14 }
 15
 16 inline int lowbit(int x) {
 17     return x & -x;
 18 }
 19
 20 void modify(int k, int val) {
 21     while(k <= hcnt) {
 22         tree[k] += val;
 23         k += lowbit(k);
 24     }
 25 }
 26
 27 int get_sum(int k) {
 28     int res = 0;
 29     while(k) {
 30         res += tree[k];
 31         k -= lowbit(k);
 32     }
 33     return res;
 34 }
 35
 36 struct Node {
 37     int v, l, r, id;
 38     Node() {}
 39     Node(int v, int l, int r, int id): v(v), l(l), r(r), id(id) {}
 40     bool operator < (const Node &rhs) const {
 41         if(r != rhs.r) return r > rhs.r;
 42         if(l != rhs.l) return l < rhs.l;
 43         return (v == 0) < (rhs.v == 0);
 44     }
 45 };
 46
 47 bool cmp_id(const Node &a, const Node &b) {
 48     return a.id < b.id;
 49 }
 50
 51 Node p[MAXN];
 52 int ans[MAXN], tl[MAXN], tr[MAXN];
 53 int n;
 54
 55 void solve(int l, int r) {
 56     if(l == r) return ;
 57     int mid = (l + r) >> 1;
 58     solve(l, mid);
 59     solve(mid + 1, r);
 60     sort(p + l, p + r + 1);
 61     for(int i = l; i <= r; ++i) {
 62         if(p[i].id <= mid) {
 63             if(p[i].v) modify(p[i].l, p[i].v);
 64         } else {
 65             if(!p[i].v) ans[p[i].id] += get_sum(p[i].l);
 66         }
 67     }
 68     for(int i = l; i <= r; ++i) {
 69         if(p[i].id <= mid && p[i].v) modify(p[i].l, -p[i].v);
 70     }
 71     sort(p + l, p + r + 1, cmp_id);
 72 }
 73
 74 int main() {
 75     while(scanf("%d", &n) != EOF) {
 76         int tcnt = 0; hcnt = 0;
 77         char c;
 78         for(int i = 1, t, u; i <= n; ++i) {
 79             scanf(" %c", &c);
 80             if(c == ‘D‘) {
 81                 scanf("%d%d", &t, &u);
 82                 p[i] = Node(1, t, u, i);
 83                 hashmap[hcnt++] = t; hashmap[hcnt++] = u;
 84                 tl[++tcnt] = t; tr[tcnt] = u;
 85             }
 86             if(c == ‘C‘) {
 87                 scanf("%d", &t);
 88                 p[i] = Node(-1, tl[t], tr[t], i);
 89             }
 90             if(c == ‘Q‘) {
 91                 scanf("%d%d", &t, &u);
 92                 p[i] = Node(0, t, u, i);
 93                 hashmap[hcnt++] = t; hashmap[hcnt++] = u;
 94             }
 95         }
 96         sort(hashmap, hashmap + hcnt);
 97         hcnt = unique(hashmap, hashmap + hcnt) - hashmap;
 98         for(int i = 1; i <= n; ++i) {
 99             p[i].l = hash(p[i].l); p[i].r = hash(p[i].r);
100         }
101         memset(ans + 1, 0, n * sizeof(int));
102         solve(1, n);
103         for(int i = 1; i <= n; ++i)
104             if(p[i].v == 0) printf("%d\n", ans[i]);
105     }
106 }

ACdream 1157 Segments(CDQ分治),布布扣,bubuko.com

时间: 2024-10-14 01:49:54

ACdream 1157 Segments(CDQ分治)的相关文章

ACdream 1157 Segments CDQ分治

题目链接:https://vjudge.net/problem/ACdream-1157 题意: 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,

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

【ACdream】1157 Segments cdq分治

Segments 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 <

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) 初学CDQ分治是看了B

CDQ分治与整体二分小结

前言 这是一波强行总结. 下面是一波瞎比比. 这几天做了几道CDQ/整体二分,感觉自己做题速度好慢啊. 很多很显然的东西都看不出来 分治分不出来 打不出来 调不对 上午下午晚上的效率完全不一样啊. 完蛋.jpg 绝望.jpg. 关于CDQ分治 CDQ分治,求的是三维偏序问题都知道的. 求法呢,就是在分治外面先把一维变成有序 然后分治下去,左边(l,mid)关于右边(mid+1,r)就不存在某一维的逆序了,所以只有两维偏序了. 这个时候来一波"树状数组求逆序对"的操作搞一下二维偏序 就可

【BZOJ3963】[WF2011]MachineWorks cdq分治+斜率优化

[BZOJ3963][WF2011]MachineWorks Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先进的机械设备生产先进的机器.原来的那一台生产机器已经坏了,所以你要去为公司买一台新的生产机器.你的任务是在转型期内尽可能得到更大的收益.在这段时间内,你要买卖机器,并且当机器被ACM公司拥有的时候,操控这些机器以获取利润.因为空间的限制,ACM公司在任何时候都只能最多拥有一台机器. 在转型期内,有若

BZOJ 2225 [Spoj 2371]Another Longest Increasing(CDQ分治)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2225 [题目大意] 给定N个数对(xi,yi),求最长上升子序列的长度. 上升序列定义为{(xi,yi)}满足对i<j有xi<xj且yi<yj. [题解] CDQ分治,将每个区间按照a排序,用区间左边的数据来更新右边的最长上升序列, 为排除a相等但是b上升情况的误统计,在排序时加入下标作为第二关键字, 使得a相等的情况下标小的后更新. [代码] #include <cs

BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N行,每

HDU 5618:Jam&#39;s problem again(CDQ分治+树状数组处理三维偏序)

http://acm.hdu.edu.cn/showproblem.php?pid=5618 题意:-- 思路:和NEUOJ那题一样的.重新写了遍理解了一下,算作处理三维偏序的模板了. 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 #d