大常数人求调CDQ套CDQ
查看原帖
大常数人求调CDQ套CDQ
932169
Caiest_Oier楼主2023/3/30 20:37

本人第一次写CDQ,常数有点大,TLE只有60pts,求改进(或指出不正确的写法)。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k,ans[300003],ans2[300003],k1,k2,k3,k4,k5,k6,k7;
struct Flw{
	int val[3];
	char mk[3];
	int num;
}F[300003],stk[3][300003];
int tot;
int sum[300003];
bool comp(Flw X,Flw Y){
	if(X.val[0]!=Y.val[0])return X.val[0]<Y.val[0];
	if(X.val[1]!=Y.val[1])return X.val[1]<Y.val[1];
	if(X.val[2]!=Y.val[2])return X.val[2]<Y.val[2];
	return X.num<Y.num;
}
void cdq(int dms,int l,int r){
	if(l==r)return;
	cdq(dms,l,((l+r)>>1));cdq(dms,((l+r)>>1)+1,r);
	for(int i=l;i<=r;i++)F[i].mk[dms]=(i>((l+r)>>1));
	tot=0;
	k1=l;
	k2=((l+r)>>1)+1;
	k4=((l+r)>>1);
	while(1){
		while(k1<=k4&&F[k1].val[dms]<=F[k2].val[dms])stk[dms][++tot]=F[k1++];
		if(k1>k4)break;
		while(k2<=r&&F[k2].val[dms]<F[k1].val[dms])stk[dms][++tot]=F[k2++];
		if(k2>r)break;
	}
	while(k1<=k4)stk[dms][++tot]=F[k1++];
	while(k2<=r)stk[dms][++tot]=F[k2++];
	for(int i=l;i<=r;i++)F[i]=stk[dms][i-l+1];
	if(dms!=2){
		cdq(dms+1,l,r);
		for(int i=l;i<=r;i++)F[i]=stk[dms][i-l+1];
	}
	else{
		k3=0;
		for(int i=l;i<=r;i++){
			if(F[i].mk[0]==0&&F[i].mk[1]==0&&F[i].mk[2]==0)k3++;
			if(F[i].mk[0]&&F[i].mk[1]&&F[i].mk[2])ans[F[i].num]+=k3;
		}
	}
	return;
}
signed main(){
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&F[i].val[0],&F[i].val[1],&F[i].val[2]);
	sort(F+1,F+n+1,comp);
	for(int i=1;i<=n;i++)F[i].num=i;
	k1=n;
	for(int i=n;i>0;i--){
		if(F[i].val[0]!=F[k1].val[0]||F[i].val[1]!=F[k1].val[1]||F[i].val[2]!=F[k1].val[2])k1=i;
		ans[i]+=(k1-i);
	}
	for(int i=1;i<=n;i++){
		F[i].val[0]*=200000;
		F[i].val[0]+=i;
		F[i].val[1]*=200000;
		F[i].val[1]+=i;
		F[i].val[2]*=200000;
		F[i].val[2]+=i;
	}
	cdq(0,1,n);
	for(int i=1;i<=n;i++)ans2[ans[i]]++;
	for(int i=0;i<n;i++)printf("%lld\n",ans2[i]);
	return 0;
}
2023/3/30 20:37
加载中...