bzoj3263 陌上花开 CDQ模板

3262: 陌上花开

Time Limit: 20 Sec  Memory Limit: 256 MB
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3262

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
题解:三维偏序模板,一维排序,二维分治, 三维树状数组
注意把相同的数压在一起后贡献是加上他的size;
#include<bits/stdc++.h>
using namespace std;
const int M = 200000+5;
int n, k, cnt;
int c[M], ans[M], vis[M];

struct Thing{int a, b, c, siz, ans;}tmp[M], p[M], rt[M];
bool cmp(Thing A, Thing B){
    if(A.a != B.a)return A.a < B.a;
    if(A.b != B.b)return A.b < B.b;
    return A.c < B.c;
    
}
inline int lowbit(int x){return x & (-x);}
void modify(int pos, int val){
    for(int x = pos; x <= k; x += lowbit(x))
        c[x] += val;
}
int query(int pos){
    int ret = 0;
    for(int x = pos; x; x -= lowbit(x))
        ret += c[x];
    return ret;
}
void print(){
    for(int i=1;i<=cnt;i++)printf("%d %d %d\n",rt[i].a,rt[i].b,rt[i].c);puts("");
}
void cdq(int lf, int rg){
    if(lf == rg){
        rt[lf].ans += rt[lf].siz - 1;
        return ;
    } 
    int mid = (lf + rg) >> 1;
    cdq(lf, mid); cdq(mid + 1, rg);
    int i = lf, j = mid + 1, num = lf;
    while(i <= mid && j <= rg){
        if(rt[i].b <= rt[j].b) {
            modify(rt[i].c, rt[i].siz);
            tmp[num++] = rt[i++];    
        }
        else {
            rt[j].ans += query(rt[j].c);
            tmp[num++] = rt[j++];
        }
    }
    
    while(j <= rg)rt[j].ans += query(rt[j].c), tmp[num++] = rt[j++];
    for(int z = lf; z < i; z++)modify(rt[z].c, -rt[z].siz);
    while(i <= mid)tmp[num++] = rt[i++];
    //for(int i = lf; i <= rg; i++)if(rt[i].ans)printf("%d %d\n",i,rt[i].ans);puts("");
    for(int z = lf; z <= rg; z++){
        rt[z] = tmp[z];    
    }
    //print();
}

int main(){
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++)scanf("%d%d%d", &p[i].a, &p[i].b, &p[i].c);
    sort(p + 1, p + 1 + n, cmp);
    for(int i = 1; i <= n; i++){
        if(p[i].a != p[i - 1].a || p[i].b != p[i - 1].b || p[i].c != p[i - 1].c)
            rt[++cnt] = p[i];
        rt[cnt].siz++;
    }
    cdq(1, cnt);    
    for(int i = 1; i <= cnt; i++)vis[rt[i].ans] += rt[i].siz;
    for(int i = 0; i < n; i++)printf("%d\n", vis[i]);
}
View Code

 

posted @ 2018-08-19 18:51  Ed_Sheeran  阅读(155)  评论(0编辑  收藏  举报