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 }
时间: 2024-10-10 23:02:27

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

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

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

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