ICode9

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

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

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

标签:偏序 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

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

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

ICode9版权所有