bzoj 3262: 陌上花開:http://www.lydsy.com/JudgeOnline/problem.php?id=3262
三維偏序(向我一樣不懂啥偏序的先戳這裏:http://www.cnblogs.com/AKCqhzdy/p/8017372.html)
第一個維度直接排序解決
第二個維度的話cdq搞一搞
符合條件就直接丟到樹狀數組裏去
sum=樹狀數組的getsum就ok
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct node
{
int x,tot,s,c,m; //x:沒我好看的數量 tot:屬性跟我完全一樣的個數
}a[110000];
int c[410000];
node p[110000];
int n,k;
int ans[410000];
bool cmp(node x,node y)
{
if (x.s!=y.s) return x.s<y.s;
else if (x.c!=y.c) return x.c<y.c;
else if (x.m!=y.m) return x.m<y.m;
else return false;
}
int lowbit(int x)//lowbit第一個不受到管轄的上司/兒子
{
return x&-x;
}
void add(int x,int y)
{
while (x<=k)
{
c[x]+=y;
x+=lowbit(x);
}
}
int getsum(int x)
{
int sum=0;
while (x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
void cdq(int l,int r)
{
if (l==r) return ;
int mid=(l+r)/2;
cdq(l,mid);cdq(mid+1,r);
int i=l,j=mid+1,len=l;
while (i<=mid&&j<=r)
{
if (a[i].c<=a[j].c)
{
add(a[i].m,a[i].tot);
p[len]=a[i];len++;i++;
}
else
{
a[j].x+=getsum(a[j].m);
p[len]=a[j];len++;j++;
}
}
while (i<=mid)
{
add(a[i].m,a[i].tot); p[len]=a[i];len++;i++;
}
while (j<=r)
{
a[j].x+=getsum(a[j].m); p[len]=a[j];len++;j++;
}
for (int i=l;i<=mid;i++) add(a[i].m,-a[i].tot);//據說memset會T
for (int i=l;i<=r;i++) a[i]=p[i];
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
{
a[i].x=0;
scanf("%d%d%d",&a[i].s,&a[i].c,&a[i].m);
}
sort(a+1,a+1+n,cmp);
int k=1,head=0;
for (int i=1;i<=n;i+=k)
{
k=1;
while (a[i].s==a[i+k].s&&a[i].c==a[i+k].c&&a[i].m==a[i+k].m) k++;
a[++head].tot=k; a[head].s=a[i].s; a[head].c=a[i].c; a[head].m=a[i].m;
}
cdq(1,head);
for (int i=1;i<=head;i++)
{
ans[a[i].x+a[i].tot-1]+=a[i].tot;//讓自己儘量的好看就要把和自己一樣的打壓下去
}
for (int i=0;i<=n-1;i++) printf("%d\n",ans[i]);
return 0;
}