[BZOJ3262]陌上花开(cdq分治)
程序员文章站
2022-05-14 18:49:14
...
照例的传送门piu~
cdq的裸题 这是一道经典的三维偏序问题~~~
一维排序 二维cdq分治 三维树状数组
排序保证了x的有序 其次二分逐层递归 在回溯到该层的时候再进行一次排序保证y的有序性 三维用双指针搞一下放在树状数组里维护
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,t[200005],ans[100005],m,nn;
struct node{int a,b,c,ans,s;}a[100005],p[100005];
inline bool cmp(node a,node 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 operator <(node a,node b)
{
if(a.b==b.b) return a.c<b.c;
return a.b<b.b;
}
inline int lowbit(int x){return x&-x;}
inline void update(int x,int num){for(int i=x;i<=m;i+=lowbit(i))t[i]+=num;}
inline int ask(int x)
{
int tmp=0;
for(int i=x;i;i-=lowbit(i))
tmp+=t[i];
return tmp;
}
void solve(int l,int r)
{
if(l==r) return;
int mid=l+r>>1;
solve(l,mid);solve(mid+1,r);
sort(p+l,p+mid+1);sort(p+mid+1,p+r+1);
int i=l,j=mid+1;
while(j<=r)
{
while(i<=mid&&p[i].b<=p[j].b)
{
update(p[i].c,p[i].s);
i++;
}
p[j].ans+=ask(p[j].c);
j++;
}
for(int j=l;j<i;j++) update(p[j].c,-p[j].s);
}
int main()
{
scanf("%d%d",&nn,&m);
for(int i=1;i<=nn;i++) scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
sort(a+1,a+1+nn,cmp);
int cnt=0;
for(int i=1;i<=nn;i++)
{
cnt++;
if(a[i].a!=a[i+1].a||a[i].b!=a[i+1].b||a[i].c!=a[i+1].c)
{
p[++n]=a[i];
p[n].s=cnt;
cnt=0;
}
}
solve(1,n);
for(int i=1;i<=n;i++) ans[p[i].ans+p[i].s-1]+=p[i].s;
for(int i=0;i<nn;i++) printf("%d\n",ans[i]);
return 0;
}
上一篇: 真是好有压力