Published on 2017-09-02 11:31 in 暂未分类 with 散落星河的记忆🌠

# [BZOJ 3262] 陌上花开

## Description

$N$ 朵花，每朵花有三个属性：花形(s)、颜色(c)、气味(m)，又三个整数表示。现要对每朵花评级，一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花 A 比另一朵花 B 要美丽，当且仅当 $s_A\ge s_B,c_A\ge c_B ,m_A\ge m_B$。显然，两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

## 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

$1 \le N \le 100000, 1 \le K \le 200000$

CDQ分治模板题。

## Code

#include <cstdio>
#include <algorithm>

const int N = 100005;
struct Node {
int a, b, c, n, v;
bool operator < (const Node &rhs) const {
return a == rhs.a ? (b == rhs.b ? c < rhs.c : b < rhs.b) : a < rhs.a;
}
} a[N], b[N];
int n, m = 1, K, ans[N], sum[N << 1];

int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x;
}
void clear(int x) {
while (x <= K) {
if (!sum[x]) break;
sum[x] = 0, x += x & (-x);
}
}
void update(int x, int y) {
while (x <= K) sum[x] += y, x += x & (-x);
}
int query(int x) {
int res = 0;
while (x) res += sum[x], x -= x & (-x);
return res;
}
void solve(int l, int r) {
if (l >= r) return;
int mid = (l + r) >> 1, p = l, q = mid + 1, t = 0;
solve(l, mid), solve(mid + 1, r);
while (p <= mid && q <= r) {
if (a[p].b <= a[q].b) update(a[p].c, a[p].n), b[t++] = a[p++];
else a[q].v += query(a[q].c), b[t++] = a[q++];
}
if (p <= mid) {
for (int i = l; i < p; ++i) clear(a[i].c);
while (p <= mid) b[t++] = a[p++];
} else if (q <= r) {
while (q <= r) a[q].v += query(a[q].c), b[t++] = a[q++];
for (int i = l; i <= mid; ++i) clear(a[i].c);
}
for (int i = 0; i < t; ++i) a[l + i] = b[i];
}
int main() {