洛谷 P2061 [USACO07OPEN]City Horizon S

Description

洛谷传送门

Solution

我们发现我们是无法快速判断一个区间内我们需要修改哪些数,不需要修改哪些数的。同时我们观察到整个区间初始全为 0.

所以我们考虑对询问进行排序,按修改高度从低到高排序。

排完序后,我们对于每一个操作就相当于进行区间修改了(现在区间内的数一定小于等于要修改的数,所以直接区间赋值即可)。

我们使用线段树进行维护,最后输出根节点的区间和即可。

另外,这道题还要离散化,把 \(1e9\) 的坐标范围改到 \(8e4\)(每次询问有 \(l\),\(r\) 两个坐标)。

而且这道题还要调可恶的边界,因为输入的是轮廓线,这个并不是类似于点权的东西,而是要修改中间的部分,大概类似于开区间?

建议把区间的 \(l\),\(r\) 都存到结构体里,这样就不用调这么多了。

总之在线段树 \(build\) 函数中递归调用时要调用 \((l,mid)\) 和 \((mid,r)\),简单来说 \(mid\) 不需要 +1。

且要判断 \(l == r- 1\) 时,退出。具体见代码吧。

最后别忘了开 \(long\ long\)。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ls rt << 1
#define rs rt << 1 | 1
#define ll long long

using namespace std;

inline ll read(){
	ll x = 0;
	char ch = getchar();
	while(ch < '0' || ch > '9') ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
	return x;
}

const ll N = 1e5 + 10;
ll n, ans;
struct Query{
	ll l, r;
	ll h;
	bool operator < (const Query &b) const{
		return h < b.h;
	}
}q[N];
ll pos[N << 1], cnt;
struct Seg_tree{
	ll l, r, sum, lazy;
}t[N << 2];

inline void pushup(ll rt){
	t[rt].sum = t[ls].sum + t[rs].sum;
}

inline void pushdown(ll rt){
	if(t[rt].lazy){
		t[ls].sum = t[rt].lazy * (pos[t[ls].r] - pos[t[ls].l]);
		t[rs].sum = t[rt].lazy * (pos[t[rs].r] - pos[t[rs].l]);
		t[ls].lazy = t[rs].lazy = t[rt].lazy;
		t[rt].lazy = 0;
	}
}

inline void build(int l, int r, int rt){
	t[rt].l = l, t[rt].r = r;
	if(l == r - 1) return;
	int mid = (l + r) >> 1;
	build(l, mid, ls);
	build(mid, r, rs);
}

inline void update(ll L, ll R, ll k, ll rt){
	int l = t[rt].l, r = t[rt].r;
	if(l > R || r < L) return;
	if(L <= l && r <= R){
		t[rt].sum = k * (pos[r] - pos[l]);
		t[rt].lazy = k;
		return;
	}
	pushdown(rt);
	ll mid = (l + r) >> 1;
	if(L < mid) update(L, R, k, ls);
	if(R > mid) update(L, R, k, rs);
	pushup(rt);
}

signed main(){
	freopen("P2061.in", "r", stdin);
	freopen("P2061.out", "w", stdout);
	n = read();
	for(ll i = 1; i <= n; i++){
		q[i].l = read(), q[i].r = read(), q[i].h = read();
		pos[++cnt] = q[i].l, pos[++cnt] = q[i].r;
	}
	sort(pos + 1, pos + 1 + cnt);
	ll tot = unique(pos + 1, pos + 1 + cnt) - pos - 1;
	for(ll i = 1; i <= n; i++){
		q[i].l = lower_bound(pos + 1, pos + 1 + tot, q[i].l) - pos;
		q[i].r = lower_bound(pos + 1, pos + 1 + tot, q[i].r) - pos;
	}
	sort(q + 1, q + 1 + n);
	build(1, tot, 1);
	for(ll i = 1; i <= n; i++)
		update(q[i].l, q[i].r, q[i].h, 1);
	printf("%lld\n", t[1].sum);
	return 0;
}

End

上一篇:FastAPI 学习之路(二十六)全局依赖项


下一篇:Day65_补充:JVM、SQL:索引、视图、函数和过程