散落星河的记忆🌠
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\)。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

Input

第一行为 \(N,K\),分别表示花的数量和最大属性值。

以下 \(N\) 行,每行三个整数 \(s_i, c_i, m_i~(1 \le s_i, c_i, m_i \le 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

HINT

\(1 \le N \le 100000, 1 \le K \le 200000\)

Solution

CDQ分治模板题。

首先排序消去第一维,分治时保证 \([l,mid]\) 的第二维不大于 \([mid+1,r]\) 的第二维,第三维用树状数组统计。

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 read() {
	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() {
	n = read(), K = read();
	for (int i = 1; i <= n; ++i) a[i].a = read(), a[i].b = read(), a[i].c = read(), a[i].n = 1;
	std::sort(a + 1, a + n + 1);
	for (int i = 2; i <= n; ++i)
		if (a[i - 1] < a[i]) a[++m] = a[i]; else ++a[m].n;
	solve(1, m);
	for (int i = 1; i <= m; ++i) ans[a[i].v + a[i].n - 1] += a[i].n;
	for (int i = 0; i < n; ++i) printf("%d\n", ans[i]);
	return 0;
}
A man can be destroyed, but not defeated.
posted @ 2019-02-15 19:18  散落星河的记忆🌠  阅读(105)  评论(0编辑  收藏  举报