ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【模板】三维偏序(陌上花开)

2021-07-22 11:02:13  阅读:114  来源: 互联网

标签:偏序 sort int 陌上 mid long while 模板


[模板] 三维偏序(陌上花开)

Solution:

CDQ分治求解三维偏序。
1、首先三关键字排序,保证接下来\(i\)的可行解一定在\([1,i-1]\)中。

2、再对第二关键字做归并排序,保证满足\(a_j<a_i\)的前提下,实现\(b_j<b_i\)。合并时有两个区间,\(j<i\),\(j\)在\([l,mid]\)中,\(i\)在\([mid+1,r]\)中,由于前一次对三关键字的排序,使得左区间所有\(a\)小于等于右区间所有\(a\),所以在归并维护答案时,无需顾忌\(a\)的情况,靠双指针来保证\(b\)有序,然后同时统计\(c\)的答案即可。

3、归并时双指针与树状数组维护第三关键字对答案的贡献,注意重复三维点的情况。

Code:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+20;
inline int read() {
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
    return x*f;
}
inline void out(int x) {   
	if(x>9) out(x/10);   
	putchar(x%10+'0'); 
}
int n,k;
struct node{
	int a,b,c;
	int cnt;
	int sum;
	void print(){
		cout<<"a="<<a<<" b="<<b<<" c="<<c<<" cnt="<<cnt<<" sum="<<sum<<endl;
	}
	bool operator < (const node &t)const{
		if(t.a!=a)return a<t.a;
		if(t.b!=b)return b<t.b;
		return c<t.c;
	}
	bool operator == (const node &t)const{
		return t.a==a&&t.b==b&&t.c==c;
	}
	node():a(0),b(0),c(0),cnt(0),sum(0){}
	node(int _a,int _b,int _c,int _cnt,int _sum):a(_a),b(_b),c(_c),cnt(_cnt),sum(_sum){}
}q[N],w[N],kep[N];

int ans[N];
#define lowbit(x) (x&(-x))
int c[N];
void add(int pos,int val){
	while(pos<N){
		c[pos]+=val;
		pos+=lowbit(pos);
	}
}
int geta(int pos){
	int ans=0;
	while(pos){
		ans+=c[pos];
		pos-=lowbit(pos);
	}
	return ans;
}

void merge_sort(int l,int r){
	if(l==r)return ;
	int mid = (l+r)>>1;
	merge_sort(l,mid),merge_sort(mid+1,r);
	int i=l,j=mid+1;
	int k=0;
	while(i<=mid&&j<=r){
		if(q[i].b<=q[j].b)add(q[i].c,q[i].cnt),w[k++]=q[i++];
	
		else q[j].sum+=geta(q[j].c),w[k++]=q[j++];
	}
	while(i<=mid)add(q[i].c,q[i].cnt),w[k++]=q[i++];
	while(j<=r)q[j].sum+=geta(q[j].c),w[k++]=q[j++];
	for(int o=l;o<=mid;++o)add(q[o].c,-q[o].cnt);

	for(int i=0,st=l;i<k;++i){
		q[st+i] = w[i];
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>k;
	rep(i,1,n){
		int x,y,z;
		cin>>x>>y>>z;
		q[i]=node(x,y,z,1,0);
	}
	sort(q+1,q+1+n);
	int siz=0;
	for(int i=1;i<=n;++i){
		int pos = i;
		int cnt = 0;
		while(pos<=n&&q[pos]==q[i]){
			pos++;	
			cnt++;
		}
		kep[++siz] = q[i];
		kep[siz].cnt = cnt;
		i=pos-1;
	}
	for(int i=1;i<=siz;++i){
		q[i] = kep[i];
	}
	merge_sort(1,siz);
	for(int i=1;i<=siz;++i){
		ans[q[i].cnt-1+q[i].sum]+=q[i].cnt;
	}
	for(int i=0;i<n;++i){
		cout<<ans[i]<<"\n";
	}
	return 0;
}                  

标签:偏序,sort,int,陌上,mid,long,while,模板
来源: https://www.cnblogs.com/quuns/p/15043107.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有