CDQ分治。
今天学姐讲课讲到了这个东西,所以就拿这道例题练练手(于是就给自己挖了一个大坑)
由于学姐并没有给代码,于是到网上找了题解当板子学(from Po姐)
zyz大神独立码出CDQ分治,吓得蒟蒻赶紧膜拜(其实是拿来代码看。。。)
于是就出事了。
zyz大神的方法是先无脑向左右CDQ下去,然后按第三维sort、计算右半边的答案,最后按照第二维排序;
Po姐的方法是先按第一维sort,再向左CDQ,计算答案,再向右CDQ,最后按照第二维排序。
由于CDQ的时间不同,排序方法也不同,导致蒟蒻调了一晚上。。。
感觉还是zyz大神的方式比较适合食用。
顺便说一下一个非常显然但是总是让蒟蒻搞错的地方:STL的sort有两个指针。。第一个指针指向开始节点。。第二个指针指向结束节点。。然而。。这个结束节点是不会被用来排序的!是不会被用来排序的!是不会被用来排序的!
这导致我对zyz大神的代码误解了n个小时。。。mdzz
扔一下zyz大神的blog,可以用来学习算法,观摩代码就算了,,,码风过于独特,儿童慎入!
#include<cstdio>
#include<algorithm>
using namespace std;
#define lowbit(x) x&(-x)
const int N=1e5+10;
struct node
{
int x,y,z,cnt,ans;
inline bool operator <(const node other)const
{
if(x==other.x)
if(y==other.y) return z<other.z;
else return y<other.y;
else return x<other.x;
}
}a[N],t[N];
int ans[N],bit[N<<1],Time[N<<1];
int n,k,tot,Times;
inline bool cmp(const node a,const node b)
{
if(a.y==b.y) return a.z<b.z;
return a.y<b.y;
}
inline void add(int i,int num)
{
for(;i<=k;i+=lowbit(i))
if(Time[i]==Times) bit[i]+=num;
else bit[i]=num,Time[i]=Times;
}
inline int ask(int i)
{
int ans=0;
for(;i;i-=lowbit(i))
if(Time[i]==Times) ans+=bit[i];
return ans;
}
void CDQ(int l,int r)
{
if(l==r)
{
a[l].ans+=a[l].cnt-1;
return;
}
int mid=(l+r)>>1,tmp1=l,tmp2=mid+1,tmp=l;
for(int i=l;i<=r;i++)
if(a[i].x<=mid&&tmp1<=mid) t[tmp1++]=a[i];
else t[tmp2++]=a[i];
for(int i=l;i<=r;i++)
a[i]=t[i];
CDQ(l,mid);
Times++;
for(int i=mid+1;i<=r;i++)
{
while(tmp<=mid&&a[tmp].y<=a[i].y) add(a[tmp].z,a[tmp].cnt),tmp++;
a[i].ans+=ask(a[i].z);
}
CDQ(mid+1,r);
tmp1=l,tmp2=mid+1;
for(int i=l;i<=r;i++)
if(tmp1<=mid&&(tmp2>r||a[tmp1].y<=a[tmp2].y)) t[i]=a[tmp1++];
else t[i]=a[tmp2++];
for(int i=l;i<=r;i++)
a[i]=t[i];
}
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].cnt=1;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
if(a[i].x!=a[i-1].x||a[i].y!=a[i-1].y||a[i].z!=a[i-1].z) a[++tot]=a[i];
else a[tot].cnt++;
for(int i=1;i<=tot;i++)
a[i].x=i;
sort(a+1,a+tot+1,cmp);
CDQ(1,tot);
for(int i=1;i<=tot;i++)
ans[a[i].ans]+=a[i].cnt;
for(int i=0;i<n;i++)
printf("%d\n",ans[i]);
return 0;
}