三维偏序

题解:

显然第一维可以排序

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.线段树套平衡树

显然可以用这个维护每一个数之前有几个

原文地址:https://www.cnblogs.com/yinwuxiao/p/8433886.html