bzoj 3262

 

题意:给你一些三维上的点,对于每个点,统计三个坐标都小于等于该点的点数。

 

如果点的范围在300以内,可以用三维树状数组搞,但这题坐标范围太大。

考虑将所有点按照x坐标排序,从左到右,相当于在一个二维平面上插入点,并询问某个点左下方的点数,而后者可以按时间分治,在O(nloglog)复杂度内搞定。(其实可以把x轴看成时间轴)

 

注意相同点的处理。

(感觉对时间分治就是:将左区间和右区间的修改对其后面的询问的贡献处理掉,合并时就只有左区间的修改和右区间的询问,这就达到了以一个log的复杂度将"修改 询问 修改 修改 询问...”的问题变成了“修改 修改 修改 询问 询问”)

 1 #include <cstdio>
 2 #include <algorithm>
 3 #define N 100010
 4 #define K 200010
 5 using namespace std;
 6 
 7 struct Trid {
 8     int x, y, z;
 9     int cnt;
10     int xx;
11     Trid(){}
12     Trid( int x, int y, int z ):x(x),y(y),z(z),cnt(0),xx(x){}
13     bool operator==( const Trid & o ) const {
14         return x==o.x && y==o.y && z==o.z;
15     }
16     bool operator<( const Trid &b ) const {
17         if( x!=b.x ) return x<b.x;
18         if( y!=b.y ) return y<b.y;
19         return z<b.z;
20     }
21 };
22 
23 int n, k;
24 Trid trid[N];
25 int bit[K];
26 int ans[N];
27 
28 void modify( int pos, int v ) {
29     for( int i=pos; i<=k; i+=i&-i )
30         bit[i] += v;
31 }
32 int query( int pos ) {
33     int rt=0;
34     for( int i=pos; i; i-=i&-i )
35         rt += bit[i];
36     return rt;
37 }
38 bool cmp_yzx( const Trid &a, const Trid &b ) {
39     if( a.y!=b.y ) return a.y<b.y;
40     if( a.z!=b.z ) return a.z<b.z;
41     return a.x<b.x;
42 }
43 void cdq( int lf, int rg ) {
44     if( lf==rg ) return;
45     int mid=(lf+rg)>>1;
46     cdq(lf,mid);
47     cdq(mid+1,rg);
48     sort( trid+lf, trid+rg+1, cmp_yzx );
49     for( int i=lf; i<=rg; i++ ) {
50         if( trid[i].x<=mid )
51             modify( trid[i].z, +1 );
52         if( trid[i].x>mid )
53             trid[i].cnt += query( trid[i].z );
54     }
55     for( int i=lf; i<=rg; i++ )
56         if( trid[i].x<=mid )
57             modify( trid[i].z, -1 );
58 }
59 int main() {
60     scanf( "%d%d", &n, &k );
61     for( int i=1,x,y,z; i<=n; i++ ) {
62         scanf( "%d%d%d", &x, &y, &z );
63         trid[i] = Trid( x, y, z );
64     }
65     sort( trid+1, trid+1+n );
66     for( int i=1,j; i<=n; i++ ) {
67         for( j=i; j<=n && trid[j]==trid[i]; j++ );
68         for( int k=i; k<j; k++ )
69             trid[k].cnt += j-k-1;
70         i = j-1;
71     }
72     for( int i=1; i<=n; i++ )
73         trid[i].x = i;
74     cdq( 1, n );
75     for( int i=1; i<=n; i++ ) {
76         ans[trid[i].cnt]++;
77     }
78     for( int i=0; i<n; i++ )
79         printf( "%d\n", ans[i] );
80 }
View Code

 

posted @ 2015-04-25 18:04  idy002  阅读(231)  评论(0编辑  收藏  举报