其他分享
首页 > 其他分享> > cdq入门

cdq入门

作者:互联网

cdq不是一个具体的算法,它是一种思想。cdq之于分治,就像区间dp之于dp。

三维偏序

模板题
思路,先考虑二维。排序使第一维有序,然后顺序遍历,第二位用树状数组维护。
如果把顺序遍历,改成如归并排序的方式,题目仍然可行,但多了一个logn。
三维情况下,就可以先排序使第一维有序,再向下递归。向上合并时保证第二维有序,每次合并时用树状数组维护第三维即可
据说cdq还能处理四维偏序,但暂时还不会

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=2e5+100;
template<typename T>
inline void read(T &x){
	x=0;T fl=1;char tmp=getchar();
	while(tmp<'0'||tmp>'9')fl=tmp=='-'?-fl:fl,tmp=getchar();
	while(tmp>='0'&&tmp<='9')x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
	x=x*fl;
}
int n,k;
struct node{
	int a,b,c,id;
}p[maxn];
int t[maxn],f[maxn];
inline int lowbit(const int x){return x&-x;}
inline void add(int x){
	while(x<=k){
		t[x]++;
		x+=lowbit(x);
	}
}
inline void mns(int x){
	while(x<=k){
		t[x]--;
		x+=lowbit(x);
	}
}
inline int ask(int x){
	int ans=0;
	while(x){
		ans+=t[x];
		x-=lowbit(x);
	}
	return ans;
}
bool cmp_a(const node x,const node y){
	if(x.a!=y.a)return x.a<y.a;
	if(x.b!=y.b)return x.b<y.b;
	if(x.c!=y.c)return x.c<y.c;
	return x.id<y.id;
}
bool cmp_b(const node x,const node y){
	if(x.b!=y.b)return x.b<y.b;
	if(x.c!=y.c)return x.c<y.c;
	return x.id<y.id;
}
bool cmp(const node x,const node y){
	return x.id<y.id;
}
void solve(int l,int r){
	if(l==r)return ;
	int mid=l+r>>1;
	solve(l,mid),solve(mid+1,r);
	int i=mid+1,j=l;
	while(i<=r){
		while(p[j].b<=p[i].b&&j<=mid)add(p[j].c),j++;
		f[p[i].id]+=ask(p[i].c),i++;
	}
	for(int i=l;i<j;i++)
		mns(p[i].c);
	sort(p+l,p+r+1,cmp_b);
}
int cnt[maxn];
signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++)
		read(p[i].a),read(p[i].b),read(p[i].c),p[i].id=i;
	sort(p+1,p+n+1,cmp_a);
	solve(1,n);
	sort(p+1,p+n+1,cmp_a);
	for(int i=n-1;i>=1;i--)
		if(p[i].a==p[i+1].a&&p[i].b==p[i+1].b&&p[i].c==p[i+1].c)
			f[p[i].id]=f[p[i+1].id];
	for(int i=1;i<=n;i++)
		cnt[f[i]]++;
	for(int i=0;i<n;i++)
		printf("%d\n",cnt[i]);
//	for(int i=1;i<=n;i++)
//		printf("%d\n",f[i]);
	return 0;
}

标签:tmp,入门,int,while,cdq,&&,fl
来源: https://www.cnblogs.com/xyc1719/p/16560238.html