洛谷 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;
}