cdq分治学习笔记
cdq分治:可解决n维偏序
题意:有 $ n $ 个元素,第 $ i $ 个元素有 $ a_i,b_i,c_i $ 三个属性,设 $ f(i) $ 表示满足 $ a_j \leq a_i $ 且 $ b_j \leq b_i $ 且 $ c_j \leq c_i $ 且 $ j \ne i $ 的 \(j\) 的数量。对于 $ d \in [0, n) $,求 $ f(i) = d $ 的数量。
做法:
对于第一维 \(a\) , 排序
对于第二位 \(b\) , 归并
对于第三维 \(c\) , 数据结构维护
每次归并考虑区间 \([l,mid]\) 对 \([mid+1,r]\) 的贡献(满足第一维条件)
第二维在左右区间取较小值 左区间add加贡献 右区间query查答案
注意相同元素能互相产生贡献 所以需要去重
#include<bits/stdc++.h>
using namespace std;
#define inl inline
#define ll long long
#define endl '\n'
#define int ll
const int N=3e5+5;
const int M=1e5+5;
const int inf=0x3f3f3f3f;
const int base=131;
const int mod=1e9+7;
inl int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*f;
}
inl void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
inl void writei(int x){write(x);putchar(' ');}
inl void writel(int x){write(x);putchar(endl);}
bool st;
int t,n,k,cnt,c[N],res[N];
struct node{
int a,b,c,w,ans;
friend bool operator<(node x,node y){return (x.a^y.a)?x.a<y.a:(x.b^y.b)?x.b<y.b:x.c<y.c;}
}x[N],a[N],b[N];
inl void update(int x,int v){
for(;x<=k;x+=x&-x)c[x]+=v;
}
inl int query(int x){
int ans=0;
for(;x;x-=x&-x)ans+=c[x];
return ans;
}
inl void cdq(int l,int r){
if(l==r)return;
int mid=l+r>>1;
cdq(l,mid);cdq(mid+1,r);
int lp=l,rp=mid+1,cnt=l;
while(lp<=mid&&rp<=r){
if(a[lp].b<=a[rp].b){
update(a[lp].c,a[lp].w);
b[cnt++]=a[lp++];
}else{
a[rp].ans+=query(a[rp].c);
b[cnt++]=a[rp++];
}
}
while(lp<=mid)update(a[lp].c,a[lp].w),b[cnt++]=a[lp++];
while(rp<=r)a[rp].ans+=query(a[rp].c),b[cnt++]=a[rp++];
for(int i=l;i<=mid;i++)update(a[i].c,-a[i].w);
for(int i=l;i<=r;i++)a[i]=b[i];
}
bool ed;
signed main(){
n=read();k=read();
for(int i=1;i<=n;i++)x[i]={read(),read(),read(),1};
sort(x+1,x+n+1);
for(int i=1;i<=n;i++){
if((x[i].a^a[cnt].a)||(x[i].b^a[cnt].b)||(x[i].c^a[cnt].c))a[++cnt]=x[i];
else a[cnt].w++;
}
cdq(1,cnt);
for(int i=1;i<=cnt;i++)res[a[i].ans+a[i].w-1]+=a[i].w;
for(int i=0;i<n;i++)writel(res[i]);
return 0;
}

浙公网安备 33010602011771号