三维偏序
题解:
显然第一维可以排序
1.cdq分治
考虑前一半对后一半的影响
只需将左右两半排序,然后第三维树状数组维护就行
注意的是对于相同元素要好好处理
1是要把相同元素去重 2是排序的时候要注意
代码:
#include <bits/stdc++.h>
using namespace std;
#define N 210000
#define lowbit(x) (x&(-x))
struct re{
int a,b,c,d;
}a[N],b[N],aa[N];
int f[N],p[N],ans[N],n,k,l;
bool cmp(re x,re y)
{
return(x.a<y.a||(x.a==y.a&&x.b<y.b)||
(x.a==y.a&&x.b==y.b&&x.c<y.c)) ;
}
bool cmp2(re x,re y)
{
return(x.b<y.b||(x.b==y.b&&x.c<y.c)
||(x.b==y.b&&x.c==y.c&&x.a<y.a));
}
queue<int> q;
void insert(int x,int w)
{
while (x<=k)
{
q.push(x); p[x]+=w; x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while (x)
{
ans+=p[x];
x-=lowbit(x);
}
return(ans);
}
#define mid (h+t)/2
void cdq_fz(int h,int t)
{
if (h==t) return;
for (int i=h;i<=t;i++) b[i]=a[i],b[i].a=i;
sort(b+h,b+t+1,cmp2);
for (int i=h;i<=t;i++)
if (b[i].a<=mid) insert(b[i].c,b[i].d);
else f[b[i].a]+=query(b[i].c);
while (!q.empty()) p[q.front()]=0,q.pop();
cdq_fz(h,mid); cdq_fz(mid+1,t);
}
int main()
{
cin>>n>>k; int nn=n;
for (int i=1;i<=n;i++) cin>>a[i].a>>a[i].b>>a[i].c;
sort(a+1,a+1+n,cmp);
// for (int i=1;i<=n;i++)
// cout<<a[i].a<<" "<<a[i].b<<" "<<a[i].c<<endl;
for (int i=1;i<=n;i++)
if (a[i].a==a[i-1].a&&a[i].b==a[i-1].b&&a[i].c==a[i-1].c)
aa[l].d++;
else aa[++l].a=a[i].a,aa[l].b=a[i].b,aa[l].c=a[i].c,aa[l].d=1;
memcpy(a,aa,sizeof(aa)); n=l;
cdq_fz(1,n);
for(int i=1;i<=n;i++) ans[f[i]+a[i].d-1]+=a[i].d;
for (int i=0;i<=nn-1;i++) cout<<ans[i]<<endl;
return 0;
}
2.线段树套平衡树
显然可以用这个维护每一个数之前有几个