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
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
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]); }