http://www.lydsy.com/JudgeOnline/problem.php?id=3262
有人说有O(nlogn)的不sort的方法,简直是胡扯。。。
中间还不是O(nlogn)的BIT。。。
一样的T(n)=2T(n/2)+O(nlogn)自己算算、、、
一定要先去重么。。。?
jcvb:
关键在于等号的处理。按a排序,并把a值相同的三元组放到一个段内。CDQ分治时以段为最小单位,这样每次将序列分成两部分时,可以保证左半部分的a都严格 小于右半部分的a,于是我们可以统计a'<a,b'<=b,c'<=c的数量。可以证明这样的复杂度仍然是O(nlog^2n)。
再统计每一段内,a'==a,b'<=b,c'<=c的数量。
我的方法和这个差不多,因为如果有了重复,那么重复的之间是可能不会计算的(比如分在同一块)
也就是保证右边不能对左边不能有贡献。。。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define rep(i,l,r) for(int i=(l),_=(r);i<=_;i++)
#define per(i,r,l) for(int i=(r),_=(l);i>=_;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define INE(i,u) for(int i=head[u];~i;i=e[i].next)
#define LL long long
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
////////////////////////////////////////////////
const int N=100010;
int n,k;
struct data{int x,y,z,s,ans;}a[N],c[N];
int tot;
int ans[N];
int b[2*N];
////////////////////////////////////////////////
inline bool cmp(const data &A,const data &B)
{
if(A.x!=B.x) return A.x<B.x;
if(A.y!=B.y) return A.y<B.y;
return A.z<B.z;
}
inline bool cmp2(const data &A,const data &B)
{
if(A.y!=B.y) return A.y<B.y;
return A.z<B.z;
}
void add(int o,int x){for(;o<=k;o+=o&-o)b[o]+=x;}
int query(int o){int s=0;for(;o;o-=o&-o)s+=b[o];return s;}
void cdq(int l,int r)
{
if(l==r) return;
int mid=l+r>>1;
cdq(l,mid); cdq(mid+1,r);
int i=l,j=mid+1;
for(;j<=r;j++)
{
for(;i<=mid && c[i].y <= c[j].y;i++)
{
add(c[i].z,c[i].s);
}
c[j].ans+=query(c[j].z);
}
rep(j,l,i-1) add(c[j].z,-c[j].s); // 清空,妈呀是i-1不是mid,该死!
sort(&c[l],&c[r+1],cmp2);
}
////////////////////////////////////////////////
void input()
{
n=read(); k=read();
rep(i,1,n) a[i].x=read(), a[i].y=read(), a[i].z=read();
sort(&a[1],&a[n+1],cmp);
}
void solve()
{
int cnt=0;
rep(i,1,n)
{
cnt++;
if(memcmp(&a[i],&a[i+1],sizeof(a[i])))
memcpy(&c[++tot],&a[i],sizeof(a[i])),c[tot].s=cnt,cnt=0;
}
cdq(1,tot);
rep(i,1,tot) ans[c[i].ans+c[i].s-1]+=c[i].s;
rep(i,0,n-1) printf("%d\n",ans[i]);
}
////////////////////////////////////////////////
int main()
{
//freopen("_.in","r",stdin); freopen("_.out","w",stdout);
input(),solve();
return 0;
}