BZOJ 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
题意 : 三维偏序裸题
代码示例 :
#include<bits/stdc++.h> using namespace std; #define ll long long const int maxn = 1e5+5; typedef pair<int, int>P; #define fi first #define se second int n, m; struct node { int x, y, z; int num, cnt; // num等级 , cnt 数量 node(int _x=0, int _y=0, int _z=0):x(_x), y(_y), z(_z){} bool operator< (const node &v)const{ if (x == v.x && y == v.y) return z < v.z; else if (x == v.x) return y < v.y; return x < v.x; } }arr[maxn], f[maxn]; int k = 1; int c[maxn*2]; int lowbit(int x){return x&(-x); } void add(int p, int num){ for(int i = p; i <= m; i += lowbit(i)) c[i] += num; } int query(int p){ int sum = 0; for(int i = p; i ; i -= lowbit(i)){ sum += c[i]; } return sum; } void CDQ(int l, int r){ if (l == r) return; int mid = (l+r)>>1; CDQ(l, mid); CDQ(mid+1, r); int p1 = l, p2 = mid+1; int num = 0; for(int i = l; i <= r; i++){ if (p1<=mid && (p2 > r || arr[p1].y <= arr[p2].y)){ add(arr[p1].z, arr[p1].cnt); f[num++] = arr[p1++]; } else { int num2 = query(arr[p2].z); arr[p2].num += num2; f[num++] = arr[p2++]; } } num = 0; for(int i = l; i <= r; i++) { if (i <= mid) add(arr[i].z, -arr[i].cnt); arr[i] = f[num++]; } } int ans[maxn]; int main () { int x, y, z; cin >> n >> m; for(int i = 1; i <= n; i++){ scanf("%d%d%d", &x, &y, &z); arr[i] = node(x, y, z); arr[i].num = arr[i].cnt = 1; } sort(arr+1, arr+1+n); for(int i = 2; i <= n; i++){ if (arr[i].x == arr[k].x && arr[i].y == arr[k].y && arr[i].z == arr[k].z){ arr[k].num++; arr[k].cnt++; } else arr[++k] = arr[i]; } CDQ(1, k); for(int i = 1; i <= k; i++){ ans[arr[i].num-1] += arr[i].cnt; } for(int i = 0; i < n; i++) printf("%d\n", ans[i]); return 0; }
东北日出西边雨 道是无情却有情