陈丹琪分治

http://wenku.baidu.com/link?url=Nq_9vn-F1a8xOarR8XVdGVzMISDDQETGRU2-5q9moFr8SVqLhsOcDgUDMfCR_994pNiHtYFoK0lTe0BXnl4tNIc-UWas7VnIvvfE8hw8UwO

cdq提出的一种分治手段。

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=88335#problem/B

题意,+ a b操作是增加一个线段【a,b】,?c d 是询问此前有多少个线段满足a<=c<d<=b

暴力n^2

如果所有的查询都在增加线段之后,我们可以把线段和查询都按照左端点从小到大排序,然后单调队列两个指针。当线段左端点a<=查询c的时候,线段指针后移,并将线段的右端点加入树状数组中,当遇到a>c的时候,说明此后的线段都不满足了,这个查询的答案就是树状数组中y》=d的个数,可以用sum(MAX)-sum(y-1)得出,复杂度logn,然后查询的指针后移一个,这样每个查询和每个线段都只会走一次,总体复杂度nlogn。类似离线的查询。

但是这个题目中插入和查询的穿插出现的,就是在线的查询,通过cdq分治就可以转换为上述离线的查询。

分治思想是解决上述问题定义为solve(l,r),答案就是solve(1,n)

每次将区间等分为l到mid,mid+1到r

左区间的+都可以对右区间的?产生贡献,并且时间上都早于右边的查询,因此可以利用上诉离线算法在nlogn内完成,

然后递归解决左右区间内部的问题。logn。

总体复杂度n*log(n)*log(n)

  1 //#define debug
  2 //#define txtout
  3 #include<cstdio>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<cctype>
  8 #include<ctime>
  9 #include<iostream>
 10 #include<algorithm>
 11 #include<vector>
 12 #include<queue>
 13 #include<stack>
 14 #include<map>
 15 #include<set>
 16 #define mt(a,b) memset(a,b,sizeof(a))
 17 using namespace std;
 18 typedef long long LL;
 19 const double eps=1e-8;
 20 const double pi=acos(-1.0);
 21 const int inf=0x3f3f3f3f;
 22 const int M=5e5+10;
 23 struct G {
 24     char op[4];
 25     int x,y,id;
 26     friend bool operator <(const G &a,const G &b){
 27         return a.x<b.x;
 28     }
 29 } g[M];
 30 vector<int> a;
 31 vector<G> p,q;
 32 map<int,int> mp;
 33 int res[M];
 34 class One_Tree_Array { //一维树状数组
 35     typedef int typev;
 36     typev a[M];
 37 public:
 38     void init() {
 39         mt(a,0);
 40     }
 41     int lowb(int t) {
 42         return t&(-t);
 43     }
 44     void add(int i,typev v) {
 45         for(; i<M; a[i]+=v,i+=lowb(i));
 46     }
 47     typev sum(int i) {
 48         typev s=0;
 49         for(; i>0; s+=a[i],i-=lowb(i));
 50         return s;
 51     }
 52 }tree;
 53 int bigy;
 54 void cdq(int L,int R) {
 55     if(L==R) return ;
 56     int mid=(L+R)>>1;
 57     p.clear();
 58     for(int i=L; i<=mid; i++) {
 59         if(g[i].op[0]==‘?‘) continue;
 60         p.push_back(g[i]);
 61     }
 62     q.clear();
 63     for(int i=mid+1; i<=R; i++) {
 64         if(g[i].op[0]==‘+‘) continue;
 65         q.push_back(g[i]);
 66     }
 67     sort(p.begin(),p.end());
 68     sort(q.begin(),q.end());
 69     int lp=p.size();
 70     int lq=q.size();
 71     int len=0;
 72     for(int i=0,j=0;i<lq;i++){
 73         while(j<lp&&p[j].x<=q[i].x){
 74             tree.add(p[j].y,1);
 75             j++;
 76             len=j;
 77         }
 78         res[q[i].id]+=tree.sum(bigy)-tree.sum(q[i].y-1);
 79     }
 80     for(int i=0;i<len;i++){
 81         tree.add(p[i].y,-1);
 82     }
 83     cdq(L,mid);
 84     cdq(mid+1,R);
 85 }
 86 int main() {
 87 #ifdef txtout
 88     freopen("in.txt","r",stdin);
 89     freopen("out.txt","w",stdout);
 90 #endif
 91     int n;
 92     while(~scanf("%d",&n)) {
 93         a.clear();
 94         for(int i=1; i<=n; i++) {
 95             scanf("%s%d%d",g[i].op,&g[i].x,&g[i].y);
 96 //            a.push_back(g[i].x);
 97             a.push_back(g[i].y);
 98         }
 99         sort(a.begin(),a.end());
100         int la=unique(a.begin(),a.end())-a.begin();
101         mp.clear();
102         for(int i=0; i<la; i++) {
103             mp[a[i]]=i+1;
104         }
105         bigy=0;
106         for(int i=1; i<=n; i++) {
107 //            g[i].x=mp[g[i].x];
108             g[i].y=mp[g[i].y];
109             bigy=max(bigy,g[i].y);
110             g[i].id=i;
111             res[i]=0;
112         }
113         tree.init();
114         cdq(1,n);
115         for(int i=1; i<=n; i++) {
116             if(g[i].op[0]==‘+‘) continue;
117             printf("%d\n",res[i]);
118         }
119     }
120     return 0;
121 }

end

时间: 2024-10-27 03:42:24

陈丹琪分治的相关文章

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]这个线段,线

写给OIer们的一些话

该博客因为里面有某一段话的原因,请仅在选手中点对点分享,而不是大范围传播.我不太希望让家长看到. 我是一个高二的OIer,离我正式退役的日子已经不超过一年了.在这个时期,与其写一些回忆性的文字,不如跳出"自我"的范畴,以一种比较全局的角度和大家一起分享一些我对OI的认知和看法.目的是让初三高一的学弟学妹看清眼前的路,让高二高三的人了解自己走过的足迹. 一.独特的模式 知识的更新 我们先从OI的比赛日程谈起.选手获得NOIP一等奖后,可以报名参加WC(时间为1-2月).而在5月,选手即使

摩基亚Mokia

P1948 - [BOI2007]摩基亚Mokia Description 摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统.和其他的定位系统一样,它能够迅速回答任何形如"用户C的位置在哪?"的问题,精确到毫米.但其真正高科技之处在于,它能够回答形如"给定区域内有多少名用户?"的问题. 在定位系统中,世界被认为是一个W * W的正方形区域,由1 * 1的方格组成.每个方格都有一个坐标(x,y),1<=x,y<=W.坐标的编号从1开始

2014ACM-ICPC广州站题解(摘自闭幕式)

第39届ACM-ICPC亚洲区广州站题解 Ltysky摘抄自闭幕式题目分析 Problem A 满足px+qy=c的点(x,y)在一条直线上,而c的值由直线的截距确定,所以最大化c,就要在糖果(x,y)点集的凸包上根据斜率确定一个顶点,所以本题需要动态凸包算法,但是动态凸包只能处理加点,要删点的话需要结合陈丹琦分治. Problem B 坑题,栅栏可以套另一个,这种情况下面积是大的. Problem C 将字符串建trie图,然后满足条件的字符串分为以下两类: 它是一个前缀,同时也是一个后缀.这

BZOJ1176---[Balkan2007]Mokia (CDQ分治 + 树状数组)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176 CDQ第一题,warush了好久.. CDQ分治推荐论文: 1 <从<Cash>谈一类分治算法的应用> 陈丹琦 2 <浅谈数据结构题的几个非经典解法>  许昊然 关于CDQ分治,两种要求:①操作不相互影响  ②可以离线处理 题目描述是有问题的,,初始时 全部为0,不是s 题意:二维平面内,两种操作,1 x y v ,位于(x,y)的值加上v...2 x1,

学习笔记: cdq分治

今年的课程有很大一部分内容是cdq分治及其扩展(也就是二进制分组),拜读后觉得还是蛮有用的,这里小小地总结一下.(话说自己草稿箱里还有好多学习笔记的半成品呢,真是弱爆了.顺便感谢下fy与wxl向我介绍了那么好的东西) 推荐论文: 1 <从<Cash>谈一类分治算法的应用> 陈丹琦 2 <浅谈数据结构题的几个非经典解法>  许昊然 Q: cdq分治和普通的分治有什么区别? A: 在我们平常使用的分治中,每一个子问题只解决它本身(可以说是封闭的).而在cdq分治中,对于划分

【BZOJ】1492: [NOI2007]货币兑换Cash(cdq分治)

http://www.lydsy.com/JudgeOnline/problem.php?id=1492 蒟蒻来学学cdq神算法啊.. 详见论文 陈丹琦<从<Cash>谈一类分治算法的应用> orz 此题表示被坑精度.....导致没1a...开小号交了几发....................坑. 蒟蒻就说说自己的理解吧.. 首先这题神dp...(表示完全看不出来) 首先我们要最大化钱,那么可以将问题转化为最大化A券!(或B券)!!!!这点太神了,一定要记住这些!! 设d[i]表

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分治写的和shi一样 参悟了好长时间才大概知道CDQ分治该怎么搞,按照网上的资料半抄半写弄了道BZOJ3262陌上花开,但是评测不了,只把样例给过了,所以仍然不知道这个板子是不是对的. 以下叙述都是博主从其他BLOG里东拼西凑的: CDQ分治用来解决一类可离线的问题,通常是有一堆奇奇怪怪的修改和询问,然后拿高级数据结构做来很恶心的题目. CDQ分治的基本套路: 1.把待处理区间[l,r]分为[l,mid]和[mid+1,r]两个区间,递归处理下去. 2.处理[l,mid]区间的修改