【BZOJ 3262】-陌上花开(CDQ分治+树状数组)
CDQ分治练习题
首先以第一维为关键字排序
然后这样就只剩两维了
就像常规的分治一样
处理二维偏序关系就可以了
将满足第二维关系的的三维放在一个树状数组维护查询就可以了
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=400005;
struct flw{
int a,b,c,cnt,ans;
}a[N],p[N];
inline bool cmp(const flw &a,const flw &b){
if(a.a==b.a&&a.b==b.b)return a.c<b.c;
if(a.a==b.a)return a.b<b.b;
return a.a<b.a;
}
inline bool comp(const flw &a,const flw &b){
if(a.b==b.b)return a.c<b.c;
return a.b<b.b;
}
int tr[N],n,m,tot,cnt,ans[N];
inline int lowbit(int x){return (x&(-x));}
inline void update(int pos,int k){for(;pos<=m;pos+=lowbit(pos))tr[pos]+=k;}
inline int query(int pos,int res=0){for(;pos;pos-=lowbit(pos))res+=tr[pos];return res;}
#define mid ((l+r)>>1)
inline void cdq(int l,int r){
if(l==r)return;
cdq(l,mid),cdq(mid+1,r);
sort(a+l,a+mid+1,comp);
sort(a+mid+1,a+r+1,comp);
int i=l;
for(int j=mid+1;j<=r;j++){
while(i<=mid&&a[i].b<=a[j].b){
update(a[i].c,a[i].cnt),i++;
}
a[j].ans+=query(a[j].c);
}
for(int j=l;j<i;j++)update(a[j].c,-a[j].cnt);
}
#undef mid
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
p[i].a=read(),p[i].b=read(),p[i].c=read();
}
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;i++){
cnt++;
if(p[i].a!=p[i+1].a||p[i].b!=p[i+1].b||p[i].c!=p[i+1].c){
a[++tot]=p[i],a[tot].cnt=cnt,cnt=0;
}
}
cdq(1,tot);
for(int i=1;i<=n;i++){
ans[a[i].ans+a[i].cnt-1]+=a[i].cnt;
}
for(int i=0;i<n;i++){
cout<<ans[i]<<"\n";
}
}