【BZOJ】3262: 陌上花开

3262: 陌上花开

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 4031  Solved: 1902
[Submit][Status][Discuss]

Description

有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。
现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
 

Input

第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

Output

包含N行,分别表示评级为0...N-1的每级花的数量。

Sample Input

10 3
3 3 3
2 3 3
2 3 1
3 1 1
3 1 2
1 3 1
1 1 2
1 2 2
1 3 2
1 2 1

Sample Output

3
1
3
0
1
0
1
0
0
1

HINT

 

Source

 
[Submit][Status][Discuss]


HOME Back

三维偏序模板题。套路:第一维排序,第二维cdq,第三维树状数组。cdq的具体方法类似于归并排序,将左区间和右区间递归处理。把左右区间按第二维排序,双指针扫描,当右区间i一定时,在左边扫j,当第二维还满足条件时,在值域树状数组上找到j第三维的值,加上相同类型j的个数。当第二维j超过i时,在树状数组上查询小于等于i第三维的j的个数,更新答案。最后一定要把树状数组还原。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int n, k, num[200005];

struct node {
    int a, b, c, w, ans;
} qwq[100005], qaq[100005];

bool cmp1 ( node a, node b ) {
    if ( a.a == b.a ) {
        if ( a.b == b.b ) return a.c < b.c;
        return a.b < b.b;
    }
    return a.a < b.a;
}

bool cmp2 ( node a, node b ) {
    if ( a.b == b.b ) return a.c < b.c;
    return a.b < b.b;
}

int lowbit ( int x ) {
    return x & -x;
}

int pre[200005];

void add ( int x, int d ) {
    for ( int i = x; i <= k; i += lowbit ( i ) )
        pre[i] += d;
}

int query ( int x ) {
    int ans = 0;
    for ( int i = x; i; i -= lowbit ( i ) )
        ans += pre[i];
    return ans;
}

void CDQ ( int l, int r ) {
    if ( l == r ) return ;
    int mid = ( l + r ) >> 1;
    CDQ ( l, mid ); CDQ ( mid + 1, r );
    int i = mid + 1, j = l;
    sort ( qaq + l, qaq + mid + 1, cmp2 );
    sort ( qaq + mid + 1, qaq + r + 1, cmp2 );
    for ( ; i <= r; i ++ ) {
        while ( qaq[j].b <= qaq[i].b && j <= mid ) {
            add ( qaq[j].c, qaq[j].w ); j ++;
        }
        qaq[i].ans += query ( qaq[i].c );
    }
    for ( i = l; i < j; i ++ ) add ( qaq[i].c, -qaq[i].w );
}

int main ( ) {
    //freopen ( "testdata.in", "r", stdin );
    //freopen ( "a.out", "w", stdout );
    scanf ( "%d%d", &n, &k );
    for ( int i = 1; i <= n; i ++ )
        scanf ( "%d%d%d", &qwq[i].a, &qwq[i].b, &qwq[i].c );
    sort ( qwq + 1, qwq + 1 + n, cmp1 );
    int cnt = 0, sum = 0;
    for ( int i = 1; i <= n; i ++ ) {
        cnt ++;
        if ( qwq[i].a != qwq[i+1].a || qwq[i].b != qwq[i+1].b || qwq[i].c != qwq[i+1].c ) {
            qaq[++sum] = qwq[i];
            qaq[sum].w = cnt;
            cnt = 0;
        }
    }
    CDQ ( 1, sum );
    for ( int i = 1; i <= sum; i ++ ) num[qaq[i].ans + qaq[i].w - 1] += qaq[i].w;
    for ( int i = 0; i < n; i ++ ) printf ( "%d\n", num[i] );
    return 0;
}

 【8.21更新】CDQ里面用sort很慢啊qwq,直接开个辅助数组归并比较优秀。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int n, k, tot;
int ans[100005];

struct node {
    int a, b, c, sum, ans;
} init[100005], flower[100005];

bool cmp ( node a, node b ) {
    if ( a.a == b.a ) {
        if ( a.b == b.b ) return a.c < b.c;
        return a.b < b.b;
    }
    return a.a < b.a;
}

int lowbit ( int x ) {
    return x & -x;
}

int pre[200005];
void add ( int pos, int d ) {
    for ( int i = pos; i <= k; i += lowbit ( i ) )
        pre[i] += d;
}

int query ( int pos ) {
    int ans = 0;
    for ( int i = pos; i; i -= lowbit ( i ) )
        ans += pre[i];
    return ans;
}

node fz[100005];
void CDQ ( int L, int R ) {
    if ( L == R ) return ;
    int mid = ( L + R ) >> 1; int qwq = 0;
    CDQ ( L, mid ); CDQ ( mid + 1, R );
    int i = L, j = mid + 1;
    while ( i <= mid && j <= R ) {
        if ( flower[i].b <= flower[j].b ) {
            add ( flower[i].c, flower[i].sum );
            fz[++qwq] = flower[i++];
        } else {
            flower[j].ans += query ( flower[j].c );
            fz[++qwq] = flower[j++];
        }
    }
    for ( ; j <= R; j ++ ) { flower[j].ans += query ( flower[j].c ); fz[++qwq] = flower[j]; }
    for ( ; i <= mid; i ++ ) { fz[++qwq] = flower[i]; add ( flower[i].c, flower[i].sum ); }
    for ( int i = L; i <= mid; i ++ ) add ( flower[i].c, -flower[i].sum );
    int o = 0;
    for ( i = L; i <= R; i ++ ) flower[i] = fz[++o];
}

int main ( ) {
    scanf ( "%d%d", &tot, &k );
    for ( int i = 1; i <= tot; i ++ )
        scanf ( "%d%d%d", &init[i].a, &init[i].b, &init[i].c );
    int cnt = 0;
    sort ( init + 1, init + 1 + tot, cmp );
    for ( int i = 1; i <= tot; i ++ ) {
        cnt ++;
        if ( init[i].a != init[i+1].a || init[i].b != init[i+1].b || init[i].c != init[i+1].c ) {
            flower[++n] = init[i];
            flower[n].sum = cnt;
            cnt = 0;
        }
    }    
    CDQ ( 1, n );
    for ( int i = 1; i <= n; i ++ ) ans[flower[i].ans+flower[i].sum-1] += flower[i].sum;
    for ( int i = 0; i < tot; i ++ ) printf ( "%d\n", ans[i] );
    return 0;
}

 

posted @ 2018-08-16 21:05  Wans_ovo  阅读(209)  评论(0编辑  收藏  举报