社区讨论

10分WA求调,本人线段树+扫描线

P3997[SHOI2013] 扇形面积并参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mdfltih2
此快照首次捕获于
2025/07/23 14:50
7 个月前
此快照最后确认于
2025/11/04 03:53
4 个月前
查看原帖
CPP
/* 扫描线解决, 将扇形转化为线段, 每次将ln[i].l ~ ln[i].r加上1, {方法1: 查询ln[i].l ~ ln[i].r中正好为k的区域个数, 乘上ln[i].h的平方(更有可能正确)
																方法2: 查询ln[i].l ~ ln[i].r中大于等于k的区域个数, 乘上ln[i].h与ln[i - 1].h的平方差(有可能正确?)
*/
#include <bits/stdc++.h>
using namespace std;
int n, m, k;
struct line {
	int l = 0, r = 0, h = 0;
	bool operator < (line b) {
		return h < b.h;
	} 
} ln[1145140];
struct node {
	int l, r, len, sum;
} t[4 * 1145140];
int x[1145140];
void build(int id, int l, int r) {
	t[id].l = l;
	t[id].r = r;
	t[id].len = 0;
	t[id].sum = 0;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(id << 1, l, mid);
	build(id << 1 | 1, mid + 1, r);
}
void pushup(int id) {
	int l = t[id].l;
	int r = t[id].r;
	if (t[id].sum >= k) t[id].len = x[r + 1] - x[l];
	else t[id].len = t[id << 1].len + t[id << 1 | 1].len;
}
void modify(int id, int c, int d) {
	int l = t[id].l, r = t[id].r;
	if (d <= x[l] || x[r + 1] <= c) return;
	if (c <= x[l] && x[r + 1] <= d) {
		t[id].sum++;
		pushup(id);
		return;
	}
	modify(id << 1, c, d);
	modify(id << 1 | 1, c, d);
	pushup(id);
}
int main() {
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++) {
		cin >> ln[i].h >> ln[i].l >> ln[i].r;
		x[2 * i - 1] = ln[i].l;
		x[2 * i] = ln[i].r;
	}
	sort(ln + 1, ln + n + 1);
	sort(x + 1, x + 2 * n + 1);
	int tot = unique(x + 1, x + 1 + 2 * n) - (x + 1);
	build(1, 1, tot - 1);
	long long ans = 0;
	for (int i = n; i >= 1; i--) {
		if (ln[i].l <= ln[i].r) modify(1, ln[i].l, ln[i].r);
		else {
			modify(1, ln[i].l, tot - 1);
			modify(1, 1, ln[i].r);
		}
		ans += t[1].len * (ln[i].h * ln[i].h - ln[i - 1].h * ln[i - 1].h); // 暂使用第二种
	}
	cout << ans;
    return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...