题目链接:https://cn.vjudge.net/problem/HYSBZ-3262
有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),用三个整数表示。
现在要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。
定义一朵花A比另一朵花B要美丽,当且仅Sa>=Sb,Ca>=Cb,Ma>=Mb。
显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。
Input
第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。
以下N行,每行三个整数xi, yi, zi (1 <= si, ci, mi <= K),表示第i朵花的属性
Output
包含N行,分别表示评级为0...N-1的每级花的数量。
解析:CDQ分治,先对x从小到大排序,再对y从小到大排序,再对z从小到大排序
一维排序,二维分治,第三维树状数组
注意去重,
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 3e5 + 30;
struct node{
int x, y, z;
int val, id;
}a[maxn], q[maxn], tmp[maxn];
int num[maxn], book[maxn], sum[maxn];
int ans[maxn];
bool cmp(node x, node y){
if(x.x != y.x) return x.x < y.x;
else if(x.y != y.y) return x.y < y.y;
return x.z < y.z;
}
int lowbit(int x){
return x & (-x);
}
void add(int x, int val){
if(x == 0) return;
while(x < maxn) {
sum[x]+=val;
x += lowbit(x);
}
}
void del(int x) {
if(x == 0) return;
while(x < maxn) {
sum[x] = 0;
x += lowbit(x);
}
}
int query(int x){
int ans = 0;
while(x) {
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
void CDQ(int l, int r){
if(r - l <= 1) {
ans[q[l].id] = book[q[l].id] - 1;
return;
}
int mid = l + r >> 1;
CDQ(l, mid);
CDQ(mid, r);
int t1 = l, t2 = mid, cnt = 0;
while(t1 < mid && t2 < r){
if(q[t1].y <= q[t2].y){
add(q[t1].z, q[t1].val);
tmp[cnt++] = q[t1++];
}
else {
ans[q[t2].id] += query(q[t2].z);
tmp[cnt++] = q[t2++];
}
}
while(t1 < mid){
tmp[cnt++] = q[t1++];
}
while(t2 < r){
ans[q[t2].id] += query(q[t2].z);
tmp[cnt++] = q[t2++];
}
for(int i = 0; i < cnt; i++) {
q[i + l] = tmp[i];
del(tmp[i].z);
}
}
int main()
{
int n, k;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++) {
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
num[i] = 0;
ans[i] = 0;
book[i] = 0;
}
sort(a + 1, a + n + 1, cmp);
book[0] = num[0] = ans[0] = 0;
int len = 0;
for(int i = 1; i <= n; i++) {
if(a[i].x == a[i - 1].x && a[i].y == a[i - 1].y && a[i].z == a[i - 1].z) {
book[q[len - 1].id]++;
q[len - 1].val++;
continue;
}
book[i] = 1;
q[len].id = i;
q[len].x = a[i].x;
q[len].y = a[i].y;
q[len].z = a[i].z;
q[len].val = 1;
len++;
}
CDQ(0, len);
for(int i = 1; i <= n; i++) num[ans[i]]+=book[i];
for(int i = 0; i < n; i++) printf("%d\n", num[i]);
return 0;
}