TIOJ 2124:殿壬看蝴蝶
TIOJ 2124:殿壬看蝴蝶
題目大意:這裡。
解法:我們會用到 $\text{Treap}$ 跟 $\text{BIT}$,這裡的 $\text{Treap}$ 需要支援一種操作,就是給你指標,請你輸出他在陣列第幾個,可以對每個節點存它的父節點,然後就可以用一個 $\text{rk}$ 的函式,就可以 $\text{AC}$ 這題了。
$\text{Code:}$
#pragma GCC optimize("O3")
#pragma GCC target("popcnt")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define TIOJQQ ios::sync_with_stdio(false),cin.tie(0)
#define FOR(x,a,b) for(int x=a;x<=b;x++)
#define pb emplace_back
#define F first
#define S second
mt19937 seed (time (NULL));
#define rnd(l,r) uniform_int_distribution<int>(l,r)(seed)
const int SIZE = 2e5 + 5;
int n, q;
int a[SIZE];
struct Treap {
int id, sum = 0, siz = 1, prior = rnd (0, 2e9);
Treap *fa = NULL, *ls = NULL, *rs = NULL;
Treap() {}
Treap (int id) : id (id), sum (a[id]) {}
};
int siz (Treap *t) {
return t ? t->siz : 0;
}
int sum (Treap *t) {
return t ? t->sum : 0;
}
void Pull (Treap *t) {
t->siz = siz (t->ls) + siz (t->rs) + 1;
t->sum = sum (t->ls) + sum (t->rs) + a[t->id];
if (t->ls) t->ls->fa = t;
if (t->rs) t->rs->fa = t;
}
Treap *Merge (Treap *a, Treap *b) {
if (!a || !b) return a ? a : b;
if (a->prior > b->prior) {
a->rs = Merge (a->rs, b);
Pull (a);
return a;
} else {
b->ls = Merge (a, b->ls);
Pull (b);
return b;
}
}
void Split (Treap *t, Treap *&a, Treap *&b, int k) {
if (!t) {
a = b = NULL;
return;
}
if (k <= siz (t->ls)) {
b = t;
Split (t->ls, a, b->ls, k);
Pull (b);
} else {
a = t;
Split (t->rs, a->rs, b, k - siz (t->ls) - 1);
Pull (a);
}
}
int rk (Treap *t, bool isl = 0) {
int re = (isl ? 0 : siz (t->ls) + 1);
if (t->fa == NULL) return re;
if (t->fa->ls == t) return re + rk (t->fa, 1);
return re + rk (t->fa, 0);
}
Treap *to[SIZE], *root = NULL;
int bit[SIZE];
void update (int pos, int x) {
for (; pos <= n; pos += pos & -pos) bit[pos] += x;
}
int query (int pos) {
int re = 0;
for (; pos; pos -= pos & -pos) re += bit[pos];
return re;
}
void Swap (int l1, int r1, int l2, int r2) {
Treap *t1, *t2, *t3, *t4;
Split (root, root, t4, r2);
Split (root, root, t3, l2 - 1);
Split (root, t2, root, r1);
Split (t2, t1, t2, l1 - 1);
root = Merge (Merge (Merge (t1, t3), root), Merge (t2, t4));
}
void Change (int i, int w) {
Treap *t1, *t2;
Split (root, root, t2, i);
Split (root, t1, root, i - 1);
int id = root->id;
update (id, w - a[id]);
a[id] = w;
root->sum = w;
root = Merge (Merge (t1, root), t2);
}
void solve() {
cin >> n >> q;
FOR (i, 1, n) {
cin >> a[i];
to[i] = new Treap (i);
root = Merge (root, to[i]);
update (i, a[i]);
}
while (q--) {
int ty;
cin >> ty;
if (ty == 1) {
int i, j;
cin >> i >> j;
i = rk (to[i]), j = rk (to[j]);
if (i > j) swap (i, j);
Swap (i, i, j, j);
}
if (ty == 2) {
int i, j;
cin >> i >> j;
if (i > j) swap (i, j);
Swap (i, i, j, j);
}
if (ty == 3) {
int i, w;
cin >> i >> w;
Change (rk (to[i]), w);
}
if (ty == 4) {
int i, w;
cin >> i >> w;
Change (i, w);
}
if (ty == 5) {
int l1, r1, l2, r2;
cin >> l1 >> r1 >> l2 >> r2;
if (l1 > l2) {
swap (l1, l2);
swap (r1, r2);
}
Swap (l1, r1, l2, r2);
}
if (ty == 6) {
int i;
cin >> i;
Treap *t1, *t2;
Split (root, t1, root, i - 1);
Split (root, root, t2, 1);
cout << root->id << '\n';
root = Merge (Merge (t1, root), t2);
}
if (ty == 7) {
int i;
cin >> i;
cout << rk (to[i]) << '\n';
}
if (ty == 8) {
int l, r;
cin >> l >> r;
cout << query (r) - query (l - 1) << '\n';
}
if (ty == 9) {
int l, r;
cin >> l >> r;
Treap *t1, *t2;
Split (root, root, t2, r);
Split (root, t1, root, l - 1);
cout << root->sum << '\n';
root = Merge (Merge (t1, root), t2);
}
}
}
int main() {
TIOJQQ;
solve();
}
我的分享就到這裡結束了,如果喜歡我的 $\text{Blog}$,歡迎追蹤!
留言
張貼留言