NEU 1704 三维偏序(CDQ分治+树状数组)
来源:互联网 发布:淘宝化妆品店推荐 编辑:程序博客网 时间:2024/05/21 18:33
1702: 撩妹全靠魅力值
时间限制: 10 Sec 内存限制: 128 MB提交: 164 解决: 28
[提交][状态][讨论版]
题目描述
我们永远都要相信,世界是美好的,这不是一个看脸的社会。一个人的魅力主要体现在三个方面, 一方面是颜值,颜值虽然可以在很多方面让我们感受到不一样的快乐,但是它是决定不了一个人魅力;另一方面 是内涵,内涵对于一个人魅力的提升有着巨大的作用,比如高晓松啊,黄渤啊,对吧。还有一方面是智慧,一个 人的智慧值越高,那么他在未来的道路上会在一定程度上走的更平坦一些。一个人的魅力值是相对于周围人来说的,如果他的颜值,内涵和智慧值同时不低于另外一个人,那么他的魅力值就会加1,给你一些人的颜值,内涵,和智慧值,请输出这些人的魅力值。
输入
测试样例T(T<=10) 输入的人的数量n(n<=100000) 接下来n行每行三个数个数 表示这个人的颜值,内涵,智慧值(1~100000)。
输出
每个人的魅力值。
样例输入
1410 4 710 6 68 2 57 3 10
样例输出
1100
经典的三维偏序问题,cdq分治同样也是经典的做法。
不考虑这种方法的话,我们可以先对所有的数字按照x坐标排序,然后按顺序把另外两个坐标添加进二维树状数组里面,每次查询它前面的数字个数即可。然而这里总共有100000个数字,开二维树状数组即使在离散化的情况下,也会爆内存,于是貌似只能用CDQ分治。
首先当然的,对x进行排序,然后为了分治的方便,就直接把x坐标离散化。然后直接进入分治,由于这题的cdq分治在单位区间的时候不需要进行什么修改,所以我们大可以先分治两个小部分,再处理大的区间。对于大区间,首先处理两个小区间,同时把数据按照yzx的顺序归并排序,然后从头开始依次进行插入和计算。对于x小于等于mid的点,我们把它的z坐标加入一维树状数组中,然后对于x大于mid的点,我们则统计小于等于其z坐标的点的个数。这样一来由于加入树状数组的点的x坐标都小于等于mid,而统计的点的x大于mid,x满足偏序,有由于按照了y来排序,所以y也满足偏序,故树状数组只需要一维即可统计出其偏序。
利用cdq分治消除了x的影响,利用排序解决了y的影响,然后用树状数组统计z的个数,非常巧妙的解决了二维树状数组的空间问题。也深刻体现了cdq分治这种利用前半区间的去更新后半区间的思想。然后在实际操作中,要特别注意相等的情况,具体做法是设置一个same数组,对于相同的点我们取其最后一个数字的偏序数。具体见代码:
#include<bits/stdc++.h>#define N 100010using namespace std;struct node{int x,y,z,id;} p[N],tmp[N];int n,ans[N],same[N];struct BinaryIndexedTree{int c[N];inline int lowbit(int x){return x&-x;}inline void update(int x,int k){while (x<N){c[x]+=k;x+=lowbit(x);}}void clear(int x){while (x<N){c[x]=0;x+=lowbit(x);}}inline int getsum(int x){int ans=0;while (x>0){ans+=c[x];x-=lowbit(x);}return ans;}} BIT;bool xyz(node a,node b){ if (a.x!=b.x) return a.x<b.x; return a.y==b.y?a.z<b.z:a.y<b.y;}bool yzx(node a,node b){ if (a.y!=b.y) return a.y<b.y; return a.z==b.z?a.x<b.x:a.z<b.z;}bool id(node a,node b){ return a.id<b.id;}bool operator == (node a,node b){ return a.x==b.x&&a.y==b.y&&a.z==b.z;}void cdq(int l,int r){ if (l==r) return; int mid=(l+r)>>1; cdq(l,mid);cdq(mid+1,r); int p1=l,p2=mid+1,pp=l; while(p1<=mid&&p2<=r)//归并排序的同时根据y来进行更新或者统计 { if (yzx(p[p1],p[p2])) { if (p[p1].x<=mid) BIT.update(p[p1].z,1);//如果是前半部分那么更新 tmp[pp++]=p[p1++]; } else { if (p[p2].x>mid)//后半部分则是统计 ans[p[p2].id]+=BIT.getsum(p[p2].z); tmp[pp++]=p[p2++]; } } while(p1<=mid) tmp[pp++]=p[p1++]; while(p2<=r) { if (p[p2].x>mid) ans[p[p2].id]+=BIT.getsum(p[p2].z); tmp[pp++]=p[p2++]; } for(int i=l;i<=r;i++) { p[i]=tmp[i]; if (p[i].x<=mid) BIT.clear(p[i].z);//别忘了恢复树状数组 }}int main(){ int T_T; cin>>T_T; while(T_T--) { scanf("%d",&n); for(int i=0;i<n;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); p[i]=node{x,y,z,i}; } sort(p,p+n,xyz); memset(ans,0,sizeof(ans)); for(int i=0,j;i<n;) { for (j=i+1;j<n&&p[j]==p[i];j++); for(;i<j;i++) same[p[i].id]=p[j-1].id; } for(int i=0;i<n;i++) p[i].x=i; cdq(0,n-1); sort(p,p+n,id); for(int i=0;i<n;i++) printf("%d\n",ans[same[i]]); } return 0;}
- NEU 1704 三维偏序(CDQ分治+树状数组)
- [bzoj3262]陌上花开 三维偏序 cdq分治+树状数组
- HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
- 数据(CDQ分治+树状数组)
- 洛谷P3810(三维偏序,CDQ分治果题)
- HDU 5618 CDQ分治(三维偏序)
- CDQ分治 陌上花开(三维偏序)
- 三维偏序 树套树&cdq分治
- BZOJ1176【CDQ分治】【树状数组】
- cdq分治(以cdq分治代替树状数组为例)
- 【BZOJ 3262】陌上花开(CDQ分治+树状数组)
- 【bzoj 1176】[Balkan2007] Mokia(cdq分治+树状数组)
- [BZOJ2738]矩阵乘法(梁盾)CDQ分治+二维树状数组
- bzoj 2683: 简单题 (CDQ分治+树状数组)
- PowerOj 2392(树状数组 or CDQ分治)
- bzoj2683 简单题 (cdq分治 + 树状数组)
- suoj20 垃圾显示屏(cdq分治+树状数组)
- [BZOJ1176][Balkan2007]Mokia && CDQ分治+树状数组
- 设计模式之工厂模式
- 1127. ZigZagging on a Tree (30)
- Android 学习记录及所遇到的坑
- 欢迎使用CSDN-markdown编辑器
- mac 学习python
- NEU 1704 三维偏序(CDQ分治+树状数组)
- XML——小结二
- C++Primer习题第十一章
- 菜鸟学习历程【15-3】快速排序
- 解决SDL创建的Win32窗体无鼠标双击相应事件
- AES(车贴码查询结果站点)
- 89. Gray Code
- 注释转换(将C的注释风格转换为C++的)
- Bluetooth Low Energy Advertising Bluetooth Low Energy (BLE) conserves power by remaining in sleep m