1. 程式人生 > 其它 >洛谷 P2061 [USACO07OPEN]City Horizon S

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

本文來自部落格園,作者:{xixike},轉載請註明原文連結:https://www.cnblogs.com/xixike/p/15414105.html