【ybtoj高效進階 21172】籌備計劃(線段樹)(樹狀陣列)
阿新 • • 發佈:2021-10-27
給你一個數組,然後要你支援一些操作:
給一個位置加值或者減值,詢問最優的位置,讓一段區間裡面的位置都不能是最優位置,或讓一段區間裡面的位置可以是最優位置。
最優位置是可以作為最優位置的位置中,費用最小的。
定義一個位置的費用是每個位置到它的距離乘上每個位置的權值。
籌備計劃
題目連結:ybtoj高效進階 21172
題目大意
給你一個數組,然後要你支援一些操作:
給一個位置加值或者減值,詢問最優的位置,讓一段區間裡面的位置都不能是最優位置,或讓一段區間裡面的位置可以是最優位置。
最優位置是可以作為最優位置的位置中,費用最小的。
定義一個位置的費用是每個位置到它的距離乘上每個位置的權值。
思路
考慮用資料結構維護。
首先化簡式子:\(\sum\limits_{i=1}^n(a_i|x-i|)\)
\(x\sum\limits_{i=1}^x a_i-\sum\limits_{i=1}^xa_i\times i-x\sum\limits_{i=x+1}^na_i+\sum\limits_{i=x+1}^na_i\times i\)
不難看到分成四個部分,可以用四個樹狀陣列維護。
然後至於可以不可以作為最優點,我們用線段樹來搞,那至於找位置,我們也可以直接在這個線段樹上二分。
就好惹。
程式碼
#include<cstdio> #define ll long long using namespace std; int n, q, op, x, y, re, pl; ll maxn; char c; int read() { re = 0; c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { re = (re << 3) + (re << 1) + c - '0'; c = getchar(); } return re; } void write(int x) { if (x > 9) write(x / 10); putchar(x % 10 + '0'); } struct SZSJ {//樹狀陣列 ll val[200001]; void insert(int x, ll va) { if (x <= 0) return ; for (; x <= n; x += x & (-x)) val[x] += va; } ll query(int x) { ll re = 0; for (; x; x -= x & (-x)) re += val[x]; return re; } }T1, T2, T3, T4; struct XD_tree {//線段樹 bool ckand[200001 << 2], ckor[200001 << 2]; short lzyck[200001 << 2]; // ll val[200001 << 2], nm[200001 << 2]; void down(int now) { if (lzyck[now] != -1) { ckand[now << 1] = ckand[now << 1 | 1] = lzyck[now]; ckor[now << 1] = ckor[now << 1 | 1] = lzyck[now]; lzyck[now << 1] = lzyck[now << 1 | 1] = lzyck[now]; lzyck[now] = -1; } } void col(int now, int l, int r, int L, int R, int x) { if (L <= l && r <= R) { ckand[now] = ckor[now] = x; lzyck[now] = x; return ; } down(now); int mid = (l + r) >> 1; if (L <= mid) col(now << 1, l, mid, L, R, x); if (mid < R) col(now << 1 | 1, mid + 1, r, L, R, x); ckand[now] = ckand[now << 1] & ckand[now << 1 | 1]; ckor[now] = ckor[now << 1] | ckor[now << 1 | 1]; } void insert(int pl, ll va) { T1.insert(n - (pl - 1) + 1, va * pl); T2.insert(n - (pl - 1) + 1, -va); T3.insert(pl + 1, -va * pl); T4.insert(pl + 1, va); } ll query(int pl) { return pl * (T2.query(n - pl + 1) + T4.query(pl)) + (T1.query(n - pl + 1) + T3.query(pl)); } int get_l(int now, int l, int r, int L, int R) { if (l != r) down(now); if (L <= l && r <= R) { if (ckand[now]) return l; if (!ckor[now]) return -1; int mid = (l + r) >> 1; if (ckor[now << 1]) return get_l(now << 1, l, mid, L, R); else return get_l(now << 1 | 1, mid + 1, r, L, R); } int mid = (l + r) >> 1, re = -1; if (L <= mid) re = get_l(now << 1, l, mid, L, R); if (re != -1) return re; if (mid < R) re = get_l(now << 1 | 1, mid + 1, r, L, R); return re; } int get_r(int now, int l, int r, int L, int R) { if (l != r) down(now); if (L <= l && r <= R) { if (ckand[now]) return r; if (!ckor[now]) return -1; int mid = (l + r) >> 1; if (ckor[now << 1 | 1]) return get_r(now << 1 | 1, mid + 1, r, L, R); else return get_r(now << 1, l, mid, L, R); } int mid = (l + r) >> 1, re = -1; if (mid < R) re = get_r(now << 1 | 1, mid + 1, r, L, R); if (re != -1) return re; if (L <= mid) re = get_r(now << 1, l, mid, L, R); return re; } }T; int main() { // freopen("position.in", "r", stdin); // freopen("position.out", "w", stdout); // freopen("read.txt", "r", stdin); // freopen("write.txt", "w", stdout); n = read(); q = read(); for (int i = 1; i <= n; i++) { x = read(); if (x) T.insert(i, x); } T.lzyck[1] = T.ckand[1] = T.ckor[1] = 1; int l, r; while (q--) { op = read(); if (op == 1) { x = read(); y = read(); T.insert(x, y); } if (op == 2) { x = read(); y = read(); T.insert(x, -y); } if (op == 3) { x = read(); y = read(); T.col(1, 1, n, x, y, 1); } if (op == 4) { x = read(); y = read(); T.col(1, 1, n, x, y, 0); } l = 1, r = n; while (r - l + 1 > 2) { int mid = (l + r) >> 1; if (T.query(mid) <= T.query(mid + 1)) r = mid; else l = mid + 1; } maxn = 1e18; pl = -1; for (int i = l; i <= r; i++) { ll noww = T.query(i); if (noww < maxn) maxn = noww, pl = i; } l = T.get_r(1, 1, n, 1, pl); r = T.get_l(1, 1, n, pl, n); if (l == -1 && r == -1) { putchar('-'); putchar('1'); } else if (l == -1 || r == -1) { write(l + r + 1); } else { if (T.query(l) <= T.query(r)) write(l); else write(r); } putchar('\n'); } return 0; }