博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
CDQ解决一些三维偏序的问题
阅读量:5134 次
发布时间:2019-06-13

本文共 3745 字,大约阅读时间需要 12 分钟。

  本来几天前就该记录的东西,硬生生被我拖到了现在,太懒了。。。

  在cdq学习时,二维偏序已经解决了,无非就是先sort使第一维有序,然后再用cdq或者数据结构处理第二维。而三维偏序的时候呢,大佬的做法好像有树套树之类的,但是我不会,所以我选择cdq。

  大体的思路很简单,首先也是先使第一维有序,然后cdq把第二维由小到大合并,这时再套个线段树或者树状数组处理第三维。来几题做一下

  题目大意:一个花园里有n棵数,然后有m次询问,每次询问一个矩形里有多少颗树。

  把原有的树视为更新操作,然后每个查询分为加上(0,0)到(x1-1,y1-1)范围内的树,减去(0,0)到(x1-1,y2)范围内的树,减去(0,0)到(x2,y1-1)范围内的树,加上(0,0)到(x2,y2)范围内的树,这样就可以处理一个二维前缀和,然后用cdq分治理套树状数组处理y轴

1 #include
2 #include
3 #define lowb(x) (x&(-x)) 4 using namespace std; 5 const int N=500118,M=500118,Y=10000118,Q=(M<<2)+N;//每个查询分4个 6 struct Nop{ 7 int x,y,op,w,id; 8 friend bool operator < (const Nop &n1,const Nop &n2){ 9 return n1.x==n2.x ? n1.op
>1; 50 cdq(l,m); 51 cdq(m+1,r); 52 int i=l,j=m+1,k=l; 53 while(i<=m&&j<=r) 54 { 55 if(P[i]
园丁你为何烦恼呢

  当然,这题很明显是个二维偏序问题,因为树本身都存在了,没有什么更新操作,直接离线树状数组处理就行。

1 #include
2 #include
3 #define lowb(x) (x&(-x)) 4 using namespace std; 5 const int N=500118,M=500118,Y=10000118,Q=(M<<2)+N; 6 struct Nop{ 7 int x,y,op,w,id; 8 friend bool operator < (const Nop &n1,const Nop &n2){ 9 return n1.x==n2.x ? n1.op
园丁不烦恼了

  题目大意:维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

  S值并没有实际作用忽略就好。这题就不行像上面那题单纯的离线然后树状数组维护就行了,因为是有着一个更新的存在,不同的查询前面的更新是不一样的。所以就是我们大体的思路,把每个操作视为(操作时间,x轴,y轴)这样的带有附加消息的三维有序对,这样第一维已经有序了,我们就只需要把x轴cdq分治处理,然后y轴有树状数组处理,查询也就是维护个二维的前缀和。

1 #include
2 #include
3 #define lowb(x) (x&(-x)) 4 using namespace std; 5 const int N=160118,M=10118,Y=2001108,Q=(M<<2)+N; 6 struct Nop{ 7 int x,y,op,w,id; 8 friend bool operator < (const Nop &n1,const Nop &n2){ 9 return n1.x==n2.x ? n1.op
>1; 50 cdq(l,m); 51 cdq(m+1,r); 52 int i=l,j=m+1,k=l; 53 while(i<=m&&j<=r) 54 { 55 if(P[i]
园丁都会了这个肯定会了

  题目大意:有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

  这就是个三维偏序的问题了,没有什么更新和查询就是(s,c,m)的三维有序对求顺序对,我们同样是让sort按s由小到大,s相同按c排,c相同按m排的cmp使得第一维s有序,然后cdq分治处理第二维c,树状数组维护第三维m,最后提交,好的,wrong了。因为一个重要的点,,两朵花可能有同样的属性,如果我们不去重的话,那么相同的属性的话,因为它们的顺序不同造成它们的等级不同。所以我们把属性相同的归为一类,然后统计这一类有多少个,然后作为树状数组维护的权值维护就行,有个小细节就是当分到最小的子区间也就是只有一朵花时,它的等级应该还得提升它的权值-1,因为那些和它属性相同的合为一类了,具体的就看代码注释。

1 #include
2 #include
3 #define lowb(x) (x&(-x)) 4 using namespace std; 5 const int N=100118,K=200118; 6 struct Flower{ 7 int id,s,c,m,w; 8 friend bool operator == (const Flower &f1,const Flower &f2){ 9 return f1.s==f2.s&&f1.m==f2.m&&f1.c==f2.c; 10 } 11 }F[N],temp[N]; 12 int fn,ans[N]={
0},rank[N]={
0},summ[K]={
0}; 13 //ans[i]保存编号为i的花的等级,也就是属性小于或等于它的数目 14 bool cmp(const Flower &f1,const Flower &f2){ 15 return f1.s==f2.s ? (f1.c==f2.c ? f1.m
>1; 56 cdq(l,mid); 57 cdq(mid+1,r); 58 int i=l,j=mid+1,k=l; 59 while(i<=mid&&j<=r) 60 { 61 if(F[i].c<=F[j].c) 62 { 63 updata(F[i].m,F[i].w); 64 temp[k++]=F[i++]; 65 } 66 else 67 { 68 ans[F[j].id]+=getsum(F[j].m); 69 temp[k++]=F[j++]; 70 } 71 } 72 while(i<=mid) 73 temp[k++]=F[i++]; 74 while(j<=r) 75 { 76 ans[F[j].id]+=getsum(F[j].m); 77 temp[k++]=F[j++]; 78 } 79 for(i=l;i<=r;i++) 80 { 81 clear(F[i].m); 82 F[i]=temp[i]; 83 } 84 } 85 int main() 86 { 87 int n,k; 88 while(~scanf("%d%d",&n,&k)) 89 { 90 for(int i=0;i
公子世无双

 

转载于:https://www.cnblogs.com/LMCC1108/p/10737124.html

你可能感兴趣的文章
8、RDD持久化
查看>>
第二次团队冲刺--2
查看>>
VMware Tools安装
查看>>
Linux上架设boost的安装及配置过程
查看>>
[转载]加密算法库Crypto——nodejs中间件系列
查看>>
使用Xshell密钥认证机制远程登录Linux
查看>>
Android 画图之 Matrix(一)
查看>>
【模板】最小生成树
查看>>
设计模式之结构型模式
查看>>
poj2569
查看>>
使用pygal_maps_world.i18n中数据画各大洲地图
查看>>
jQuery EasyUI 的下拉选择combobox后台动态赋值
查看>>
timeline时间轴进度“群英荟萃”
查看>>
python if else elif statement
查看>>
网络编程
查看>>
文本隐藏(图片代替文字)
查看>>
java面试题
查看>>
提高码力专题(未完待续)
查看>>
pair的例子
查看>>
前端框架性能对比
查看>>