洛谷 P2061 [USACO07OPEN]City Horizon S
阿新 • • 發佈:2021-10-16
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