标签:def 数据 www 有一个 can 数组 sort 分时 数列
首先,偏序是什么
一维偏序就是数列中对于每个\(x\)有多少个\(a\leq x\)
二维偏序就是二元组\((x,y)\)有多少\((a,b)\)满足\(a\leq x \wedge b\leq y\)
...
一维偏序可以直接排序
二维偏序联想到逆序对可以给第一位排序第二维数据结构
三维偏序第一维排序第二维cdq分治第三维树状数组
其实二维还有一个方法就是归并排序
每次二分时顺便统计左边对右边的影响
cdq分治就是这样
没了。。??
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 300001
using namespace std;
int n,m,k,a[M],c[M],cnt[M];
struct vv { int a,b,c,id,num,ans;} d[M],tmp[M];
bool cmp(vv a,vv b)
{
if(a.a!=b.a) return a.a<b.a;
if(a.b!=b.b) return a.b<b.b;
return a.c<b.c;
}
void add(int x,int k) { for(int i=x;i<=m;i+=i & -i) c[i]+=k;}
int ask(int x) { int ans=0; for(int i=x;i>0;i-=i & -i) ans+=c[i]; return ans;}
void cdq(int l,int r)
{
if(l==r) return ;
int mid=(l+r)>>1,cnt=0, j=l;
cdq(l,mid); cdq(mid+1,r);
for(int i=mid+1;i<=r;i++)
{
while(d[j].b<=d[i].b && j<=mid) add(d[j].c,d[j].num), tmp[cnt++]=d[j++];
d[i].ans+=ask(d[i].c); tmp[cnt++]=d[i];
}
for(int i=l;i<j;i++) add(d[i].c,-d[i].num);
for(int i=mid;i>=j;i--) d[r+i-mid]=d[i];
for(int i=0;i<cnt;i++) d[l+i]=tmp[i];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d%d%d",&tmp[i].a,&tmp[i].b,&tmp[i].c), tmp[i].num=1;
sort(tmp+1,tmp+1+n,cmp);
for(int i=1;i<=n;i++)
if(tmp[i].a!=tmp[i-1].a || tmp[i].b!=tmp[i-1].b || tmp[i].c!=tmp[i-1].c) d[++k]=tmp[i], d[k].id=k;
else d[k].num+=1;
cdq(1,k);
for(int i=1;i<=k;i++) cnt[d[i].ans+d[i].num-1]+=d[i].num;
for(int i=0;i<n;i++) printf("%d\n",cnt[i]);
}
标签:def 数据 www 有一个 can 数组 sort 分时 数列
原文地址:https://www.cnblogs.com/ZUTTER/p/10383590.html