1. 程式人生 > >【BZOJ5286】【HNOI2018】轉盤(線段樹)

【BZOJ5286】【HNOI2018】轉盤(線段樹)

Description

Solution

首先發現答案就是將Ti進行輪換之後的max{Tii}+n1的最小值(考慮在起點一次性等待很長時間後,直接不停留地一路走過去)
考慮到環的條件非常麻煩,所以考慮將序列倍長,設Pi=Tii,那麼答案就變成了:mini=1n{maxj=1n{Pi+j1}+i}+n1
發現如果j列舉到2ni+1不會影響答案。
用線段樹維護區間內的maxPmini=lmid{i+

maxirPi}即可,維護的話,和BZOJ2957樓房重建差不多。

Code

/************************************************
 * Au: Hany01
 * Date: Apr 23rd, 2018
 * Prob: [BZOJ5286][HNOI2018] 轉盤
 * Email: [email protected]
************************************************/

#include<bits/stdc++.h>

using namespace std;

typedef
long long LL; typedef pair<int, int> PII; #define File(a) freopen(a".in", "r", stdin), freopen(a".out", "w", stdout) #define rep(i, j) for (register int i = 0, i##_end_ = (j); i < i##_end_; ++ i) #define For(i, j, k) for (register int i = (j), i##_end_ = (k); i <= i##_end_; ++ i) #define Fordown(i, j, k) for (register int i = (j), i##_end_ = (k); i >= i##_end_; -- i)
#define Set(a, b) memset(a, b, sizeof(a)) #define Cpy(a, b) memcpy(a, b, sizeof(a)) #define x first #define y second #define pb(a) push_back(a) #define mp(a, b) make_pair(a, b) #define ALL(a) (a).begin(), (a).end() #define SZ(a) ((int)(a).size()) #define INF (0x3f3f3f3f) #define INF1 (2139062143) #define Mod (1000000007) #define debug(...) fprintf(stderr, __VA_ARGS__) #define y1 wozenmezhemecaia template <typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; } template <typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; } inline int read() { register int _, __; register char c_; for (_ = 0, __ = 1, c_ = getchar(); c_ < '0' || c_ > '9'; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; c_ >= '0' && c_ <= '9'; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __; } const int maxn = 100005; int mn[maxn << 4], mx[maxn << 4], n; #define mid ((l + r) >> 1) #define lc (t << 1) #define rc (lc | 1) int query(int t, int l, int r, int val) { if (l == r) return l + max(val, mx[t]); if (val >= mx[rc]) return min(query(lc, l, mid, val), mid + 1 + val); return min(mn[t], query(rc, mid + 1, r, val)); } void update(int t, int l, int r, int x, int dt) { if (l == r) { mx[t] = dt; return ; } if (x <= mid) update(lc, l, mid, x, dt); else update(rc, mid + 1, r, x, dt); mx[t] = max(mx[lc], mx[rc]); if (l <= n) mn[t] = query(lc, l, mid, mx[rc]); } int main() { #ifdef hany01 File("bzoj5286"); #endif static int m, p, x, y, las; n = read(), m = read(), p = read(); For(i, 1, n) x = read(), update(1, 1, n << 1, i, x - i), update(1, 1, n << 1, i + n, x - i - n); printf("%d\n", las = (mn[1] + n - 1)); while (m --) x = read() ^ (las * p), y = read() ^ (las * p), update(1, 1, n << 1, x, y - x), update(1, 1, n << 1, n + x, y - x - n), printf("%d\n", las = (mn[1] + n - 1)); return 0; } //牆角數枝梅,凌寒獨自開。 // -- 王安石《梅》