版权声明:转载记得声明噢! https://blog.csdn.net/Richard__Luan/article/details/81393593
CDQ分治第一题。。。上次集训还认为是大神的东西,没想到现在就学了。。。
CDQ分治可以看做降维打击,大体思路是先把一段区间分为两部分,只考虑左半部分对右半部分的影响,常数小还好写,可以顶替复杂高级数据结构,只是必须离线
AC Code
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct flower
{
int x,y,z;
int cnt,ans;
}a[1000005];
int c[3000005],n,k,tot,num[1000005];
bool cmp(flower a,flower b)
{
if(a.x<b.x) return 1;
if(a.x>b.x) return 0;
if(a.y<b.y) return 1;
if(a.y>b.y) return 0;
if(a.z<b.z) return 1;
return 0;
}
bool cmp2(flower a,flower b)
{
if(a.y<b.y) return 1;
if(a.y>b.y) return 0;
if(a.z<b.z) return 1;
if(a.z>b.z) return 0;
if(a.x<b.x) return 1;
return 0;
}
inline int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
while(x<=k)
{
c[x]+=y;
x+=lowbit(x);
}
}
int ask(int x)
{
int ans=0;
while(x)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void CDQ(int l,int r)
{
if(l==r)
{
a[l].ans+=a[l].cnt-1;
return ;
}
int mid=(l+r)>>1;
CDQ(l,mid);
CDQ(mid+1,r);
sort(a+l,a+1+mid,cmp2);
sort(a+mid+1,a+r+1,cmp2);
int j=l;
for(int i=mid+1;i<=r;i++)
{
while(j<=mid&&a[j].y<=a[i].y)add(a[j].z,a[j].cnt),j++;
a[i].ans+=ask(a[i].z);
}
for(int i=l;i<j;i++)
add(a[i].z,-a[i].cnt);
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),a[i].ans=1;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
if(i!=1&&a[i].x==a[i-1].x&&a[i].y==a[i-1].y&&a[i].z==a[i-1].z)a[tot].cnt++;
else a[++tot]=a[i],a[tot].cnt=1;
CDQ(1,tot);
sort(a+1,a+tot+1,cmp);
for(int i=1;i<=tot;i++)num[a[i].ans]+=a[i].cnt;
for(int i=1;i<=n;i++)printf("%d\n",num[i]);
return 0;
}