P3810 三维偏序 cdq分治

2024-03-02 09:18
文章标签 三维 分治 cdq 偏序 p3810

本文主要是介绍P3810 三维偏序 cdq分治,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目背景https://www.luogu.org/problemnew/show/P3810

这是一道模板题

可以使用bitset,CDQ分治,K-DTree等方式解决。

题目描述

 

 

 

 

 

 

 

 

 

 

输入输出样例

输入样例#1: 复制

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

输出样例#1: 复制

3
1
3
0
1
0
1
0
0
1

说明

1≤n≤100000,1≤k≤200000 1 \leq n \leq 100000, 1 \leq k \leq 200000 1≤n≤100000,1≤k≤200000

cdq分治每次计算前一半对后一半的影响。具体地, 假设三维分别是x,y,z,先按x排序。分治时每次将前半边、后半边分别按y排序。虽然现在x的顺序被打乱了,但是前半边还是都小于后半边的,所以要是只计算前半边对后半边的偏序关系,是不会受到x的影响的。维护后一半的指针i,前一半的指针j,每次将i后移一位时,若y[j]<=y[i]则不断后移j,并不断将z[j]加入树状数组。然后再查询树状数组中有多少数小于等于z[i]。 最后要清空树状数组。

#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+5;
int Tree[maxn+10];
struct node
{int a,b,c;int ans;int num;
};
node p[maxn];
node q[maxn];
int cnt[maxn];
bool cmpa(const node &a,const node &b)
{if(a.a==b.a){if(a.b==b.b)return a.c<b.c;return a.b<b.b;}return a.a<b.a;
}
bool cmpb(const node &a,const node &b)
{return a.b<b.b;
}
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x*f;
}
inline int lowbit(int x)
{return (x&-x);
}
void add(int x,int value)
{for(int i=x; i<=maxn; i+=lowbit(i)){Tree[i]+=value;}
}
int get(int x)
{int sum=0;for(int i=x; i; i-=lowbit(i)){sum+=Tree[i];}return sum;
}
void cdq(int l,int r)
{if(l==r)return ;int mid=(l+r)>>1;cdq(l,mid);cdq(mid+1,r);sort(q+l,q+mid+1,cmpb);sort(q+mid+1,q+r+1,cmpb);int i=l,j=mid+1;for(; j<=r; j++){while(i<=mid&&q[i].b<=q[j].b){add(q[i].c,q[i].num);i++;}q[j].ans+=get(q[j].c);}for(j=l; j<i;j++)add(q[j].c,-q[j].num);
}
int main()
{memset(cnt,0,sizeof(maxn));int n=0,n_,k;n_=read();k=read();for(int i=0; i<n_; i++){p[i].a=read();p[i].b=read();p[i].c=read();p[i].ans=0;}sort(p,p+n_,cmpa);for(int i=0;i<n_;i++){int num=0;if(q[n].a!=p[i].a||q[n].b!=p[i].b||q[n].c!=p[i].c){n++;q[n].a=p[i].a;q[n].b=p[i].b;q[n].c=p[i].c;q[n].num=1;}elseq[n].num++;}//得到a b c 都不同的数组  num是出现的次数cdq(1,n);for(int i=1; i<=n; i++){cnt[q[i].ans+q[i].num-1]+=q[i].num;}for(int i=0; i<n_; i++){printf("%d\n",cnt[i]);}
}
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+15;
struct node{
int a,b,c,w,ans;
};
map<pair<int,pair<int,int> >,int >mp;
bool cmpb(const node &a,const node &b)
{return a.b<b.b;
}
node p[maxn];
int tree[maxn];
int num[maxn];
inline int lowbit(int x)
{return (x&-x);
}
void add(int x,int value)
{for(int i=x;i<maxn;i+=lowbit(i))tree[i]+=value;
}
int get(int x)
{int sum=0;for(int i=x;i;i-=lowbit(i)){sum+=tree[i];}return sum;
}
void cdq(int l,int r)
{if(l==r)return ;int mid=(l+r)>>1;cdq(l,mid);cdq(mid+1,r);sort(p+l,p+mid+1,cmpb);sort(p+mid+1,p+r+1,cmpb);int i=l;int j=mid+1;for(;j<=r;j++){while(p[i].b<=p[j].b&&i<=mid){add(p[i].c,p[i].w);i++;}p[j].ans+=get(p[j].c);}i--;for(;i>=l;i--)add(p[i].c,-p[i].w);
}
int main()
{int n,k;memset(num,0,sizeof(num));int a,b,c;scanf("%d%d",&n,&k);for(int i=0;i<n;i++){scanf("%d%d%d",&a,&b,&c);mp[make_pair(a,make_pair(b,c))]++;}int cnt=0;for(auto it=mp.begin();it!=mp.end();it++){p[cnt].a=(it->first).first;p[cnt].b=(it->first).second.first;p[cnt].c=(it->first).second.second;p[cnt].w=(it->second);p[cnt].ans=0;cnt++;}//去重cdq(0,cnt-1);for(int i=0;i<cnt;i++){num[p[i].ans+p[i].w-1]+=p[i].w;}for(int i=0;i<n;i++){printf("%d\n",num[i]);}return 0;
}

 

这篇关于P3810 三维偏序 cdq分治的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/765637

相关文章

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Vector3 三维向量

Vector3 三维向量 Struct Representation of 3D vectors and points. 表示3D的向量和点。 This structure is used throughout Unity to pass 3D positions and directions around. It also contains functions for doin

数据集 3DPW-开源户外三维人体建模-姿态估计-人体关键点-人体mesh建模 >> DataBall

3DPW 3DPW-开源户外三维人体建模数据集-姿态估计-人体关键点-人体mesh建模 开源户外三维人体数据集 @inproceedings{vonMarcard2018, title = {Recovering Accurate 3D Human Pose in The Wild Using IMUs and a Moving Camera}, author = {von Marc

Rhinoceros 8 for Mac/Win:重塑三维建模边界的革新之作

Rhinoceros 8(简称Rhino 8),作为一款由Robert McNeel & Assoc公司开发的顶尖三维建模软件,无论是对于Mac还是Windows用户而言,都是一款不可多得的高效工具。Rhino 8以其强大的功能、广泛的应用领域以及卓越的性能,在建筑设计、工业设计、产品设计、三维动画制作、科学研究及机械设计等多个领域展现出了非凡的实力。 强大的建模能力 Rhino 8支持多种建

数据集 Ubody人体smplx三维建模mesh-姿态估计 >> DataBall

Ubody开源人体三维源数据集-smplx-三维建模-姿态估计 UBody:一个连接全身网格恢复和真实生活场景的上半身数据集,旨在拟合全身网格恢复任务与现实场景之间的差距。 UBody包含来自多人的现实场景的1051k张高质量图像,这些图像拥有2D全身关键点、3D SMPLX模型。 UBody由国际数字经济学院(IDEA)提供。 (UBody was used for mesh r

三维布尔运算对不规范几何数据的兼容处理

1.前言 上一篇文章谈过八叉树布尔运算,对于规范几何数据的情况是没有问题的。 在实际情况中,由于几何数据来源不一,处理和生成方式不一,我们无法保证进行布尔运算的几何数据都是规范的,对于不规范情况有时候也有需求,这就需要兼容不规范数据情况,当然这种兼容不是一味的让步,而是对于存在有限的不规范数据的兼容处理。 2.原始数据示例 下图是一个大坝模型和之上要对其进行布尔运算的立方体。 大坝模型由

三维激光扫描点云配准外业棋盘的布设与棋盘坐标测量

文章目录 一、棋盘标定板准备二、棋盘标定板布设三、棋盘标定板坐标测量 一、棋盘标定板准备 三维激光扫描棋盘是用来校准和校正激光扫描仪的重要工具,主要用于提高扫描精度。棋盘标定板通常具有以下特点: 高对比度图案:通常是黑白相间的棋盘格,便于识别。已知尺寸:每个格子的尺寸是已知的,可以用于计算比例和调整。平面标定:帮助校准相机和激光扫描仪之间的位置关系。 使用方法 扫描棋盘: