算法笔记--Splay && Link-Cut-Tree
Splay
参考:https://tiger0132.blog.luogu.org/slay-notes
普通模板:
const int N = 1e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
int n, m;
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
if(lazy[x]) {
swap(ch[x][], ch[x][]);
lazy[ch[x][]] ^= ;
lazy[ch[x][]] ^= ;
lazy[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
push_down(y), push_down(x);///区间反转
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
push_down(x);///区间反转
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
void Find(int x) {
if(!rt) return ;
int cur = rt;
while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
Splay(cur);
}
void Insert(int x) {
int cur = rt, p = ;
while(cur && val[cur] != x) {
p = cur;
cur = ch[cur][x>val[cur]];
}
if(cur) cnt[cur]++;
else {
cur = ++ncnt;
if(p) ch[p][x>val[p]] = cur;
fa[cur] = p;
ch[cur][] = ch[cur][] = ;
val[cur] = x;
cnt[cur] = sz[cur] = ;
}
Splay(cur);
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
inline int get_min(int x) {
while(x && ch[x][]) x = ch[x][];
return x;
}
inline int get_max(int x) {
while(x && ch[x][]) x = ch[x][];
return x;
}
int Pre(int x) {
Find(x);
if(val[rt] < x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int Succ(int x) {
Find(x);
if(val[rt] > x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
void Remove(int x) {
int last = Pre(x), next = Succ(x);
Splay(last), Splay(next, last);
int del = ch[next][];
if(cnt[del] > ) cnt[del]--, Splay(del);
else ch[next][] = , push_up(next), push_up(last);
}
///区间反转
void Reverse(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
lazy[ch[y][]] ^= ;
}
void Output(int x) {
push_down(x);
if(ch[x][]) Output(ch[x][]);
if( <= val[x] && val[x] <= n) printf("%d ", val[x]);
if(ch[x][]) Output(ch[x][]);
}
void delete_root() {
if(ch[rt][]) {
int cur = ch[rt][];
while(cur && ch[cur][]) cur = ch[cur][];
Splay(cur, rt);
ch[cur][] = ch[rt][];
fa[ch[cur][]] = cur;
rt = cur;
}
else rt = ch[rt][];
fa[rt] = ;
if(rt) push_up(rt);
}
inline int NewNode(int x) {
int cur;
if(q.empty()) cur = ++ncnt;
else cur = q.front(), q.pop();
///初始化
ch[cur][] = ch[cur][] = fa[cur] = lazy[cur] = ;
val[cur] = x;
sz[cur] = cnt[cur] = ;
return cur;
}
void Recycle(int x) {
if(ch[x][]) Recycle(ch[x][]);
if(ch[x][]) Recycle(ch[x][]);
if(x) q.push(x);
}
int build(int l, int r, int *a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
inline void init() {
ncnt = rt = ch[][] = ch[][] = fa[] = sz[] = cnt[] = val[] = lazy[] = ;
}
按排名插入模板(常数较小???也许以前的方法写搓了):
inline void Newnode(int &cur, int f, int a) {
cur = ++ncnt;
fa[cur] = f;
val[cur] = a;
ch[cur][] = ch[cur][] = ;
sz[cur] = cnt[cur] = ;
}
void Insert(int x, int y) {
int p = ;
if(!rt) {
Newnode(rt, , y);
return ;
}
if(!x) {
p = rt;
sz[p]++;
while(ch[p][]) p = ch[p][], sz[p]++;
Newnode(ch[p][], p, y);
Splay(ch[p][]);
return ;
}
int u = Kth(x);
Splay(u);
Newnode(rt, , y);
ch[rt][] = ch[u][];
fa[ch[rt][]] = rt;
ch[u][] = ;
ch[rt][] = u;
fa[u] = rt;
push_up(u), push_up(rt);
}
例题:
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 2e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], ncnt = , rt = ;
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
void Rotate(int x) {
int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
void Find(int x) {
if(!rt) return ;
int cur = rt;
while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
Splay(cur);
}
void Insert(int x) {
int cur = rt, p = ;
while(cur && val[cur] != x) {
p = cur;
cur = ch[cur][x>val[cur]];
}
if(cur) cnt[cur]++;
else {
cur = ++ncnt;
if(p) ch[p][x>val[p]] = cur;
fa[cur] = p;
ch[cur][] = ch[cur][] = ;
val[cur] = x;
cnt[cur] = sz[cur] = ;
}
Splay(cur);
}
int Kth(int k) {
int cur = rt;
while(true) {
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
int Pre(int x) {
Find(x);
if(val[rt] < x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int Succ(int x) {
Find(x);
if(val[rt] > x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
void Remove(int x) {
int last = Pre(x), next = Succ(x);
Splay(last), Splay(next, last);
int del = ch[next][];
if(cnt[del] > ) cnt[del]--, Splay(del);
else ch[next][] = /*, push_up(next), push_up(last)*/;
}
int n, opt, x;
int main() {
Insert(INT_MIN);
Insert(INT_MAX);
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
scanf("%d %d", &opt, &x);
if(opt == ) Insert(x);
else if(opt == ) Remove(x);
else if(opt == ) Find(x), printf("%d\n", sz[ch[rt][]]);
else if(opt == ) printf("%d\n", val[Kth(x+)]);
else if(opt == ) printf("%d\n", val[Pre(x)]);
else printf("%d\n", val[Succ(x)]);
}
return ;
}
思路:跟区间反转相关的Splay维护的都是下标
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
int n, m;
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
if(lazy[x]) {
swap(ch[x][], ch[x][]);
lazy[ch[x][]] ^= ;
lazy[ch[x][]] ^= ;
lazy[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
void Find(int x) {
if(!rt) return ;
int cur = rt;
while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
Splay(cur);
}
void Insert(int x) {
int cur = rt, p = ;
while(cur && val[cur] != x) {
p = cur;
cur = ch[cur][x>val[cur]];
}
if(cur) cnt[cur]++;
else {
cur = ++ncnt;
if(p) ch[p][x>val[p]] = cur;
fa[cur] = p;
ch[cur][] = ch[cur][] = ;
val[cur] = x;
cnt[cur] = sz[cur] = ;
}
Splay(cur);
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
int Pre(int x) {
Find(x);
if(val[rt] < x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int Succ(int x) {
Find(x);
if(val[rt] > x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
void Remove(int x) {
int last = Pre(x), next = Succ(x);
Splay(last), Splay(next, last);
int del = ch[next][];
if(cnt[del] > ) cnt[del]--, Splay(del);
else ch[next][] = , push_up(next), push_up(last);
}
///区间反转
void Reverse(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
lazy[ch[y][]] ^= ;
}
void Output(int x) {
push_down(x);
if(ch[x][]) Output(ch[x][]);
if( <= val[x] && val[x] <= n) printf("%d ", val[x]);
if(ch[x][]) Output(ch[x][]);
}
int l, r;
int main() {
scanf("%d %d", &n, &m);
for (int i = ; i <= n+; ++i) Insert(i);
while(m--) {
scanf("%d %d", &l, &r);
Reverse(l, r);
}
Output(rt);
return ;
}
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e6 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], rev[N], lazy[N], ncnt = , rt = ;
int n, m, a[N], lmx[N], rmx[N], mx[N], sm[N];
queue<int> q;
inline int NewNode(int x) {
int cur;
if(q.empty()) cur = ++ncnt;
else cur = q.front(), q.pop();
ch[cur][] = ch[cur][] = fa[cur] = ;
rev[cur] = lazy[cur] = ;
sz[cur] = cnt[cur] = ;
mx[cur] = sm[cur] = val[cur] = x;
lmx[cur] = rmx[cur] = max(, x);
return cur;
}
void Recycle(int x) {
if(ch[x][]) Recycle(ch[x][]);
if(ch[x][]) Recycle(ch[x][]);
if(x) q.push(x);
}
inline void push_up(int x) {
int l = ch[x][], r = ch[x][];
sz[x] = sz[l] + cnt[x] + sz[r];
sm[x] = sm[l] + val[x] + sm[r];
lmx[x] = max(lmx[l], sm[l] + val[x] + lmx[r]);
rmx[x] = max(rmx[r], sm[r] + val[x] + rmx[l]);
mx[x] = max(rmx[l] + val[x] + lmx[r], max(mx[l], mx[r]));
}
inline void push_down(int x) {
int l = ch[x][], r = ch[x][];
if(lazy[x]) {
lazy[x] = rev[x] = ;
if(l) {
lazy[l] = ;
val[l] = val[x];
sm[l] = val[l] * sz[l];
lmx[l] = rmx[l] = max(, sm[l]);
mx[l] = sm[l] > ? sm[l] : val[l];
}
if(r) {
lazy[r] = ;
val[r] = val[x];
sm[r] = val[r] * sz[r];
lmx[r] = rmx[r] = max(, sm[r]);
mx[r] = sm[r] > ? sm[r] : val[r];
}
}
if(rev[x]) {
rev[l] ^= , rev[r] ^= , rev[x] = ;
swap(lmx[l], rmx[l]);
swap(lmx[r], rmx[r]);
swap(ch[l][], ch[l][]);
swap(ch[r][], ch[r][]);
} }
int build(int l, int r, int *a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
inline int ck(int x) {
return ch[fa[x]][] == x;
}
void Rotate(int x) {
int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
///区间反转
void Reverse(int x, int y) {
int u = Kth(x), v = Kth(x+y+);
Splay(u), Splay(v, u);
int son = ch[v][];
if(!lazy[son]) {
rev[son] ^= ;
swap(ch[son][], ch[son][]);
swap(lmx[son], rmx[son]);
}
push_up(v), push_up(u);
}
void Insert(int x, int y) {
for (int i = ; i <= y; ++i) scanf("%d", &a[i]);
int u = Kth(x+), v = Kth(x+);
Splay(u), Splay(v, u);
int cur = build(, y, a);
ch[v][] = cur, fa[cur] = v;
push_up(v), push_up(u);
}
void Delete(int x, int y) {
int u = Kth(x), v = Kth(x+y+);
Splay(u), Splay(v, u);
Recycle(ch[v][]);
ch[v][] = ;
push_up(v), push_up(u);
}
void Make_Same(int x, int y, int z) {
int u = Kth(x), v = Kth(x+y+);
Splay(u), Splay(v, u);
int son = ch[v][];
lazy[son] = ;
val[son] = z;
sm[son] = z*sz[son];
mx[son] = sm[son] > ? sm[son] : val[son];
lmx[son] = rmx[son] = max(, sm[son]);
push_up(v), push_up(u);
}
int Get_Sum(int x, int y) {
int u = Kth(x), v = Kth(x+y+);
Splay(u), Splay(v, u);
push_up(v), push_up(u);
return sm[ch[v][]];
}
char opt[];
int x, y, z;
int main() {
scanf("%d %d", &n, &m);
for (int i = ; i <= n+; ++i) scanf("%d", &a[i]);
a[] = a[n+] = mx[] = -;
rt = build(, n+, a);
for (int i = ; i < m; ++i) {
scanf("%s", opt);
if(opt[] == 'I') {
scanf("%d %d", &x, &y);
Insert(x, y);
}
else if(opt[] == 'D') {
scanf("%d %d", &x, &y);
Delete(x, y);
}
else if(opt[] == 'M' && opt[] == 'S') {
scanf("%d %d %d", &x, &y, &z);
Make_Same(x, y, z);
}
else if(opt[] == 'R') {
scanf("%d %d", &x, &y);
Reverse(x, y);
}
else if(opt[] == 'G') {
scanf("%d %d", &x, &y);
printf("%d\n", Get_Sum(x, y));
}
else printf("%d\n", mx[rt]);
}
return ;
}
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<cstdio>
#include<iostream>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n"; const int N = 1e6 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
int a[N];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
void Rotate(int x) {
int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
void Find(int x) {
if(!rt) return ;
int cur = rt;
while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
Splay(cur);
}
void Insert(int x, int id) {
int cur = rt, p = ;
while(cur && val[cur] != x) {
p = cur;
cur = ch[cur][x>val[cur]];
}
if(cur) cnt[cur]++;
else {
cur = ++ncnt;
if(p) ch[p][x>val[p]] = cur;
fa[cur] = p;
ch[cur][] = ch[cur][] = ;
val[cur] = x;
a[cur] = id;
cnt[cur] = sz[cur] = ;
}
Splay(cur);
}
int Kth(int k) {
int cur = rt;
while(true) {
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
int Pre(int x) {
Find(x);
if(val[rt] < x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int Succ(int x) {
Find(x);
if(val[rt] > x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
void Remove(int x) {
int last = Pre(x), next = Succ(x);
Splay(last), Splay(next, last);
int del = ch[next][];
if(cnt[del] > ) cnt[del]--, Splay(del);
else ch[next][] = , push_up(next), push_up(last);
}
int ty, k, p;
int main() {
int now = ;
Insert(-, );
Insert(, );
while(~scanf("%d", &ty) && ty) {
if(ty == ) {
scanf("%d %d", &k, &p);
Insert(p, k);
++now;
}
else if(ty == ) {
if(!now) {
printf("0\n");
continue;
}
int cur = Kth(now+);
printf("%d\n", a[cur]);
--now;
Remove(val[cur]);
}
else if(ty == ) {
if(!now) {
printf("0\n");
continue;
}
int cur = Kth();
printf("%d\n", a[cur]);
--now;
Remove(val[cur]);
}
}
return ;
}
Splay代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 2e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
int n, m, a[N];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
void Rotate(int x) {
int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
} inline int Kth(int k) {
int cur = rt;
while(true) {
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
inline void Newnode(int &cur, int f, int a) {
cur = ++ncnt;
fa[cur] = f;
val[cur] = a;
ch[cur][] = ch[cur][] = ;
sz[cur] = cnt[cur] = ;
}
void Insert(int x, int y) {
int p = ;
if(!rt) {
Newnode(rt, , y);
return ;
}
if(!x) {
p = rt;
sz[p]++;
while(ch[p][]) p = ch[p][], sz[p]++;
Newnode(ch[p][], p, y);
Splay(ch[p][]);
return ;
}
int u = Kth(x);
Splay(u);
Newnode(rt, , y);
ch[rt][] = ch[u][];
fa[ch[rt][]] = rt;
ch[u][] = ;
ch[rt][] = u;
fa[u] = rt;
push_up(u), push_up(rt);
} void Output(int x) {
if(ch[x][]) Output(ch[x][]);
printf("%d ", val[x]);
if(ch[x][]) Output(ch[x][]);
}
int x, y;
int main() {
while(~scanf("%d", &n)) {
ncnt = rt = ;
for (int i = ; i <= n; ++i) {
scanf("%d %d", &x, &y);
Insert(x, y);
}
Output(rt);
printf("\n");
}
return ;
}
树状数组代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 4e5 + ;
int n, bit[N], res[N];
pii a[N];
void add(int x, int a) {
while(x <= n) bit[x] += a, x += x&-x;
}
int Kth(int k) {
int up = log(n)/log();
int res = ;
for (int i = up; i >= ; --i) {
if(res + (<<i) > n) continue;
if(bit[res+(<<i)] < k) {
res += <<i;
k -= bit[res];
}
}
return res+;
}
int main() {
while(~scanf("%d", &n)) {
for (int i = ; i <= n; ++i) add(i, );
for (int i = ; i <= n; ++i) scanf("%d %d", &a[i].fi, &a[i].se);
for (int i = n; i >= ; --i) {
int pos = Kth(a[i].fi+);
res[pos] = a[i].se;
add(pos, -);
}
for (int i = ; i <= n; ++i) printf("%d%c", res[i], " \n"[i==n]);
for (int i = ; i <= n; ++i) bit[i] = ;
}
return ;
}
思路:按下标建树,每次将要翻转到前面的节点Splay到根上,将它的左儿子打上标记,然后把根删掉。
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
int n, m, a[N], id[N], node[N], ans[N];
pii t[N];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
if(lazy[x]) {
swap(ch[x][], ch[x][]);
lazy[ch[x][]] ^= ;
lazy[ch[x][]] ^= ;
lazy[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
push_down(y), push_down(x);
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
push_down(x);
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
} int Newnode(int x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = ;
val[cur] = x;
cnt[cur] = sz[cur] = ;
lazy[cur] = ;
return cur;
}
int build(int l, int r, int *a) {
if(l > r) return ;
int mid = l+r >> , cur = Newnode(a[mid]);
node[id[mid]] = cur;
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
void delete_root() {
int old = rt;
if(ch[rt][]) {
rt = ch[rt][];
Splay(Kth());
ch[rt][] = ch[old][];
fa[ch[rt][]] = rt;
}
else rt = ch[rt][];
fa[rt] = ;
push_up(rt);
}
int main() {
while(~scanf("%d", &n)) {
if(n == ) break;
for (int i = ; i <= n; ++i) {
scanf("%d", &a[i]);
t[i].fi = a[i];
t[i].se = i;
}
sort(t+, t++n);
for (int i = ; i <= n; ++i) id[t[i].se] = i;
rt = ncnt = ;
sz[] = cnt[] = ch[][] = ch[][] = fa[] = lazy[] = ;
rt = build(, n, a);
for (int i = ; i <= n; ++i) {
Splay(node[i]);
printf("%d%c", sz[ch[rt][]]+i, " \n"[i==n]);
lazy[ch[rt][]] ^= ;
delete_root();
}
}
return ;
}
思路:先把TOP操作和QUERY操作的值单独扣出来,然后其他的一段区间看成一个节点
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<cstdio>
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 2e5 + ;
int ch[N][], st[N], cnt[N], fa[N], sz[N], ncnt = , rt = ;
int n, m;
int T, op[N/], a[N/], node[N], tot, vc[N/], tmp;
pii t[N];
char s[];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
void Rotate(int x) {
int y = fa[x], z = fa[y], k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
inline int Kth(int k) {
int cur = rt;
while(true) {
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
inline int KTH(int k) {
int cur = rt;
while(true) {
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return st[cur] + k-sz[ch[cur][]]-;
}
}
inline void delete_root() {
if(ch[rt][]) {
int cur = ch[rt][];
while(cur && ch[cur][]) cur = ch[cur][];
Splay(cur, rt);
ch[cur][] = ch[rt][];
fa[ch[cur][]] = cur;
rt = cur;
}
else rt = ch[rt][];
fa[rt] = ;
if(rt) push_up(rt);
}
inline int NewNode(pii x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = ;
st[cur] = x.fi;
cnt[cur] = sz[cur] = x.se - x.fi + ;
return cur;
}
int build(int l, int r) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(t[mid]);
node[mid] = cur;
if(l == r) return cur;
ch[cur][] = build(l, mid-); if(ch[cur][]) fa[ch[cur][]] = cur;
ch[cur][] = build(mid+, r); if(ch[cur][]) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
inline int get(int x) {
int l = , r = tot, m = l+r >> ;
while(l <= r) {
if(t[m].fi > x) r = m-;
else if(t[m].se < x) l = m+;
else return node[m];
m = l+r >> ;
}
}
inline void init() {
tmp = ;
tot = ;
ncnt = rt = ;
ch[][] = ch[][] = st[] = cnt[] = fa[] = sz[] = ;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
scanf("%d", &T);
for (int cs = ; cs <= T; ++cs) {
init();
scanf("%d %d", &n, &m);
for (int i = ; i <= m; ++i) {
scanf("%s%d", s, &a[i]);
if(s[] == 'T') op[i] = , vc[tmp++] = a[i];
else if(s[] == 'Q') op[i] = , vc[tmp++] = a[i];
else op[i] = ;
}
vc[tmp++] = n;
sort(vc, vc+tmp);
tmp = unique(vc, vc+tmp) - vc;
for (int i = ; i < tmp; ++i) {
if(vc[i]-vc[i-] > ) t[++tot].fi = vc[i-]+, t[tot].se = vc[i]-;
t[++tot].fi = vc[i], t[tot].se = vc[i];
}
rt = build(, tot);
printf("Case %d:\n", cs);
for (int i = ; i <= m; ++i) {
if(op[i] == ) {
int cur = get(a[i]);
Splay(cur);
delete_root();
int now = rt;
while(now && ch[now][]) now = ch[now][];
ch[now][] = cur;
fa[cur] = now;
st[cur] = a[i];
sz[cur] = cnt[cur] = ;
ch[cur][] = ch[cur][] = ;
Splay(cur);
}
else if(op[i] == ) {
int cur = get(a[i]);
Splay(cur);
printf("%d\n", sz[ch[cur][]]+);
}
else printf("%d\n", KTH(a[i]));
}
}
return ;
}
思路:常规操作
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 3e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
int n, m;
int T, a[N], x, y, z, tmp;
char s[];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
if(lazy[x]) {
swap(ch[x][], ch[x][]);
lazy[ch[x][]] ^= ;
lazy[ch[x][]] ^= ;
lazy[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
push_down(y), push_down(x);///区间反转
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
push_down(x);///区间反转
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
///区间反转
void Reverse(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
lazy[ch[y][]] ^= ;
}
void Cut(int l, int r, int c) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
int cur = ch[y][];
fa[cur] = ;
ch[y][] = ;
x = Kth(c+), y = Kth(c+);
Splay(x), Splay(y, x);
fa[cur] = y;
ch[y][] = cur;
Splay(cur);
}
void Output(int x) {
push_down(x);
if(ch[x][]) Output(ch[x][]);
if( <= val[x] && val[x] <= n) printf("%d%c", val[x], " \n"[++tmp == n]);
if(ch[x][]) Output(ch[x][]);
}
inline int NewNode(int x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = ;
val[cur] = x;
sz[cur] = cnt[cur] = ;
lazy[cur] = ;
return cur;
}
int build(int l, int r, int *a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
} int main() {
for (int i = ; i < N; ++i) a[i] = i;
while(~scanf("%d %d", &n, &m)) {
if(n == - && m == -) break;
rt = ncnt = ch[][] = ch[][] = fa[] = sz[] = cnt[] = lazy[] = ;
rt = build(, n+, a);
for (int i = ; i <= m; ++i) {
scanf("%s", s);
if(s[] == 'C') {
scanf("%d %d %d", &x, &y, &z);
Cut(x, y, z);
}
else {
scanf("%d %d", &x, &y);
Reverse(x, y);
}
}
tmp = ;
Output(rt);
}
return ;
}
思路:平衡树
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e5 + ;
const int MOD = 1e6;
struct splay {
int ch[N][], cnt[N], fa[N], sz[N], ncnt, rt;
int n, m;
LL val[N];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
void Find(LL x) {
if(!rt) return ;
int cur = rt;
while(ch[cur][x>val[cur]] && x != val[cur]) cur = ch[cur][x>val[cur]];
Splay(cur);
}
void Insert(LL x) {
int cur = rt, p = ;
while(cur && val[cur] != x) {
p = cur;
cur = ch[cur][x>val[cur]];
}
if(cur) cnt[cur]++;
else {
cur = ++ncnt;
if(p) ch[p][x>val[p]] = cur;
fa[cur] = p;
ch[cur][] = ch[cur][] = ;
val[cur] = x;
cnt[cur] = sz[cur] = ;
}
Splay(cur);
}
int Kth(int k) {
int cur = rt;
while(true) {
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
int Pre(LL x) {
Find(x);
if(val[rt] < x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int Succ(LL x) {
Find(x);
if(val[rt] > x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int pre(LL x) {
Find(x);
if(val[rt] <= x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
int succ(LL x) {
Find(x);
if(val[rt] >= x) return rt;
int cur = ch[rt][];
while(ch[cur][]) cur = ch[cur][];
return cur;
}
void Remove(LL x) {
int last = Pre(x), next = Succ(x);
Splay(last), Splay(next, last);
int del = ch[next][];
if(cnt[del] > ) cnt[del]--, Splay(del);
else ch[next][] = , push_up(next), push_up(last);
}
inline int NewNode(LL x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = ;
val[cur] = x;
sz[cur] = cnt[cur] = ;
return cur;
}
inline void init() {
ncnt = rt = ch[][] = ch[][] = fa[] = sz[] = cnt[] = val[] = ;
}
}t1, t2;
int T, a, b;
int main() {
scanf("%d", &T);
t1.init();
t2.init();
t1.Insert(LONG_MIN);
t1.Insert(LONG_MAX);
t2.Insert(LONG_MIN);
t2.Insert(LONG_MAX);
LL ans = ;
while(T--) {
scanf("%d %d", &a, &b);
if(a == ) {
if(t2.sz[t2.rt] == ) t1.Insert(b);
else {
LL del, tmp = LONG_MAX;
LL pre = t2.val[t2.pre(b)];
if(pre != LONG_MIN && abs(pre - b) < tmp) {
tmp = abs(pre-b);
del = pre;
}
LL succ = t2.val[t2.succ(b)];
if(succ != LONG_MAX && abs(succ - b) < tmp) {
tmp = abs(succ-b);
del = succ;
}
(ans += tmp) %= MOD;
t2.Remove(del);
}
}
else {
if(t1.sz[t1.rt] == ) t2.Insert(b);
else {
LL del, tmp = LONG_MAX;
LL pre = t1.val[t1.pre(b)];
if(pre != LONG_MIN && abs(pre - b) < tmp) {
tmp = abs(pre-b);
del = pre;
}
LL succ = t1.val[t1.succ(b)];
if(succ != LONG_MAX && abs(succ - b) < tmp) {
tmp = abs(succ-b);
del = succ;
}
(ans += tmp) %= MOD;
t1.Remove(del); }
}
}
printf("%lld\n", ans);
return ;
}
思路:常规操作,一开始数据范围看错,一直RE
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<climits>
#include<string>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 2.2e6;
int ch[N][], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
char val[N], s[];
string t;
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
}
///区间反转
inline void push_down(int x) {
if(lazy[x]) {
swap(ch[x][], ch[x][]);
lazy[ch[x][]] ^= ;
lazy[ch[x][]] ^= ;
lazy[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
push_down(y), push_down(x);///区间反转
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
push_down(x);///区间反转
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
void Insert(char x) {
int cur = rt, p = ;
while(cur && val[cur] != x) {
p = cur;
cur = ch[cur][x>val[cur]];
}
if(cur) cnt[cur]++;
else {
cur = ++ncnt;
if(p) ch[p][x>val[p]] = cur;
fa[cur] = p;
ch[cur][] = ch[cur][] = ;
val[cur] = x;
cnt[cur] = sz[cur] = ;
}
Splay(cur);
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
inline int NewNode(char x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = lazy[cur] = ;
val[cur] = x;
sz[cur] = cnt[cur] = ;
return cur;
}
void Reverse(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
lazy[ch[y][]] ^= ;
}
void Delete(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
ch[y][] = ;
push_up(y), push_up(x);
}
int build(int l, int r, string &a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
void Insert(int x, int n) {
int u = Kth(x), v = Kth(x+);
Splay(u), Splay(v, u);
int cur = build(, n-, t);
fa[cur] = v;
ch[v][] = cur;
push_up(v), push_up(u);
Splay(cur);
}
inline void init() {
ncnt = rt = ch[][] = ch[][] = fa[] = sz[] = cnt[] = lazy[] = ;
}
int T, n, k, a, b, now = ;
int main() {
init();
Insert('#');
Insert('*');
cin >> T;
for (int i = ; i < T; ++i) {
cin >> s;
if(s[] == 'M') {
cin >> k;
now = k;
}
else if(s[] == 'I') {
cin >> n;
cin.ignore();
getline(cin, t);
Insert(now+, n);
}
else if(s[] == 'D') {
cin >> n;
Delete(now+, now+n);
}
else if(s[] == 'R') {
cin >> n;
Reverse(now+, now+n);
}
else if(s[] == 'G') {
char t = val[Kth(now+)];
if(t != '\n') putchar(t);
putchar('\n');
}
else if(s[] == 'P') --now;
else if(s[] == 'N') ++now;
}
return ;
}
思路:常规操作,REVOLVE记得取模,这个很坑
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<climits>
#include<string>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 2e5 + ;
int ch[N][], cnt[N], fa[N], sz[N], lazy[N], ncnt = , rt = ;
LL val[N], a[N], tree[N], add[N];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
int l = ch[x][], r = ch[x][];
tree[x] = min(val[x], min(tree[l], tree[r]));
sz[x] = sz[l] + sz[r] + cnt[x];
}
///区间反转
inline void push_down(int x) {
int l = ch[x][], r = ch[x][];
if(lazy[x]) {
swap(ch[x][], ch[x][]);
if(l) lazy[l] ^= ;
if(r) lazy[r] ^= ;
lazy[x] = ;
}
if(add[x]) {
if(l) val[l] += add[x], tree[l] += add[x], add[l] += add[x];
if(r) val[r] += add[x], tree[r] += add[x], add[r] += add[x];
add[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
push_down(y), push_down(x);///区间反转
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
push_down(x);///区间反转
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
} int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
inline int NewNode(LL x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = add[cur] = lazy[cur] = ;
val[cur] = x;
tree[cur] = x;
sz[cur] = cnt[cur] = ;
return cur;
}
///区间反转
void REVERSE(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
int cur = ch[y][];
lazy[cur] ^= ;
}
void ADD(int l, int r, LL z) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
val[ch[y][]] += z;
tree[ch[y][]] += z;
add[ch[y][]] += z;
push_up(y), push_up(x);
}
void REVOLVE(int l, int r, int z) {
int len = r-l+;
z = (z%len + len) % len;
if(!z) return ;
int ll = r-z+, rr = r;
int x = Kth(ll), y = Kth(rr+);
Splay(x), Splay(y, x);
int cur = ch[y][];
ch[y][] = ;
push_up(y), push_up(x);
x = Kth(l), y = Kth(l+);
Splay(x), Splay(y, x);
ch[y][] = cur;
fa[cur] = y;
push_up(y), push_up(x);
Splay(cur);
}
LL MIN(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
return tree[ch[y][]];
}
void INSERT(int x, LL y) {
int u = Kth(x+), v = Kth(x+);
Splay(u), Splay(v, u);
int cur = NewNode(y);
fa[cur] = v;
ch[v][] = cur;
push_up(v), push_up(u);
}
void DELETE(int x) {
int u = Kth(x), v = Kth(x+);
Splay(u), Splay(v, u);
ch[v][] = ;
push_up(v), push_up(u);
}
int build(int l, int r, LL *a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
inline void init() {
ncnt = rt = ch[][] = ch[][] = fa[] = sz[] = cnt[] = val[] = add[] = lazy[] = ;
tree[] = LONG_MAX;
}
int n, m, x, y;
LL z;
char s[];
int main() {
init();
scanf("%d", &n);
for (int i = ; i <= n; ++i) scanf("%lld", &a[i]);
a[] = a[n+] = LONG_MAX;
rt = build(, n+, a);
scanf("%d", &m);
for (int i = ; i <= m; ++i) {
scanf("%s", s);
if(s[] == 'A') {
scanf("%d %d %lld", &x, &y, &z);
ADD(x, y, z);
}
else if(s[] == 'R' && s[] == 'E') {
scanf("%d %d", &x, &y);
REVERSE(x, y);
}
else if(s[] == 'R' && s[] == 'O') {
scanf("%d %d %lld", &x, &y, &z);
REVOLVE(x, y, z);
}
else if(s[] == 'I') {
scanf("%d %d", &x, &y);
INSERT(x, y);
}
else if(s[] == 'D') {
scanf("%d", &x);
DELETE(x);
}
else if(s[] == 'M') {
scanf("%d %d", &x, &y);
printf("%lld\n", MIN(x, y));
}
}
return ;
}
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<climits>
#include<cstring>
using namespace std;
#define LL long long const int N = 1e5 + ;
int ch[N][], cnt[N], fa[N], sz[N], ncnt = , rt = ;
LL add[N], tree[N], val[N], a[N];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
inline void push_up(int x) {
sz[x] = sz[ch[x][]] + sz[ch[x][]] + cnt[x];
tree[x] = val[x] + tree[ch[x][]] + tree[ch[x][]];
}
///区间反转
inline void push_down(int x) {
if(add[x]) {
int l = ch[x][], r = ch[x][];
if(l) add[l] += add[x], val[l] += add[x], tree[l] += sz[l]*1LL*add[x];
if(r) add[r] += add[x], val[r] += add[x], tree[r] += sz[r]*1LL*add[x];
add[x] = ;
}
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
push_down(y), push_down(x);///区间反转
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
push_up(y), push_up(x);
}
void Splay(int x, int goal = ) {
push_down(x);///区间反转
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
int Kth(int k) {
int cur = rt;
while(true) {
push_down(cur); ///区间反转
if(ch[cur][] && k <= sz[ch[cur][]]) cur = ch[cur][];
else if(k > sz[ch[cur][]] + cnt[cur]) k -=sz[ch[cur][]] + cnt[cur], cur = ch[cur][];
else return cur;
}
}
void ADD(int l, int r, LL c) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
add[ch[y][]] += c;
tree[ch[y][]] += sz[ch[y][]]*1LL*c;
val[ch[y][]] += c;
push_up(y), push_up(x);
}
LL SUM(int l, int r) {
int x = Kth(l), y = Kth(r+);
Splay(x), Splay(y, x);
return tree[ch[y][]];
}
inline int NewNode(LL x) {
int cur;cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = add[cur] = ;
val[cur] = x;
tree[cur] = x;
sz[cur] = cnt[cur] = ;
return cur;
} int build(int l, int r, LL *a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
push_up(cur);
return cur;
}
inline void init() {
ncnt = rt = ch[][] = ch[][] = fa[] = sz[] = cnt[] = val[] = add[] = tree[] = ;
}
int n, m, l, r;
LL c;
char s[];
int main() {
init();
scanf("%d %d", &n, &m);
for (int i = ; i <= n; ++i) scanf("%lld", &a[i]);
rt = build(, n+, a);
for (int i = ; i <= m; ++i) {
scanf("%s", s);
if(s[] == 'Q') {
scanf("%d %d", &l, &r);
printf("%lld\n", SUM(l, r));
}
else if(s[] == 'C') {
scanf("%d %d %lld", &l, &r, &c);
ADD(l, r, c);
}
}
return ;
}
将树按入时间戳和出时间戳变成线性结构,然后在这个线性结构上用splay维护
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e5 + ;
int ch[N][], val[N], cnt[N], fa[N], sz[N], ncnt = , rt = ;
int n, m, a, now = ;
vector<int> g[N];
int L[N], R[N], dfn[N], x, y;
char s[];
inline int ck(int x) {
return ch[fa[x]][] == x;
}
void Rotate(int x) {
int y = fa[x], z = fa[y];
int k = ck(x), w = ch[x][k^];
ch[y][k] = w, fa[w] = y;
ch[z][ck(y)] = x, fa[x] = z;
ch[x][k^] = y, fa[y] = x;
}
void Splay(int x, int goal = ) {
while(fa[x] != goal) {
int y = fa[x], z = fa[y];
if(z != goal) {
if(ck(x) == ck(y)) Rotate(y);
else Rotate(x);
}
Rotate(x);
}
if(!goal) rt = x;
}
inline int NewNode(int x) {
int cur = ++ncnt;
ch[cur][] = ch[cur][] = fa[cur] = ;
val[cur] = abs(x);
if(x > ) L[x] = cur;
else R[-x] = cur;
return cur;
}
int build(int l, int r, int *a) {
if(l > r) return ;
int mid = l+r >> , cur = NewNode(a[mid]);
if(l == r) return cur;
if(ch[cur][] = build(l, mid-, a)) fa[ch[cur][]] = cur;
if(ch[cur][] = build(mid+, r, a)) fa[ch[cur][]] = cur;
return cur;
}
inline void init() {
ncnt = rt = ch[][] = ch[][] = fa[] = val[] = ;
}
void dfs(int u) {
dfn[++now] = u;
for (int v : g[u]) dfs(v);
dfn[++now] = -u;
}
inline int get_min(int x) {
while(x && ch[x][]) x = ch[x][];
return x;
}
inline int get_max(int x) {
while(x && ch[x][]) x = ch[x][];
return x;
}
int QUERY(int x) {
int u = L[x];
Splay(u);
return get_min(u);
}
void MOVE(int X, int Y) {
int u = L[X], v = R[X];
Splay(u), Splay(v, u);
int x = ch[u][], y = ch[v][];
int xx = get_max(x);
fa[x] = , ch[u][] = ;
fa[y] = , ch[v][] = ;
if(y && xx) ch[xx][] = y, fa[y] = xx; if(Y == ) return ;
if(QUERY(Y) == u) {
fa[x] = u, ch[u][] = x;
fa[y] = v, ch[v][] = y;
ch[xx][] = ;
return ;
} int uu = L[Y];
Splay(uu);
int vv = get_min(ch[uu][]);
Splay(vv, uu);
ch[vv][] = u;
fa[u] = vv;
}
int main() {
bool f = false;
while(~scanf("%d", &n)) {
if(f) printf("\n");
else f = true;
init();
for (int i = ; i <= n; ++i) {
scanf("%d", &a);
g[a].pb(i);
}
for (int u : g[]) {
now = ;
dfs(u);
build(, now, dfn);
}
scanf("%d", &m);
for (int i = ; i <= m; ++i) {
scanf("%s", s);
if(s[] == 'M') {
scanf("%d %d", &x, &y);
MOVE(x, y);
}
else if(s[] == 'Q') {
scanf("%d", &x);
printf("%d\n", val[QUERY(x)]);
}
}
for (int i = ; i <= n; ++i) g[i].clear();
}
return ;
}
易错点:
1.修改后记得push_up
2.一直往左子树或右子树走时记得第一步判当前节点是不是0
套板子一时爽,一直套一直爽
Link-Cut-Tree
模板:
const int N = 3e5 + ;
int f[N],v[N],s[N],r[N],hep[N],ch[N][];
inline int get(int x){
return ch[f[x]][]==x||ch[f[x]][]==x;
}
inline void pushup(int x){
s[x]=s[ch[x][]]^s[ch[x][]]^v[x];
}
inline void filp(int x){
swap(ch[x][],ch[x][]);r[x]^=;
}
inline void pushdown(int x){
if(!r[x])return;r[x]=;
if(ch[x][])filp(ch[x][]);
if(ch[x][])filp(ch[x][]);
}
inline void rotate(int x){
int y=f[x],z=f[y],k=ch[y][]==x,v=ch[x][!k];
if(get(y))ch[z][ch[z][]==y]=x;ch[x][!k]=y,ch[y][k]=v;
if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
int y=x,top=;hep[++top]=y;
while(get(y))hep[++top]=y=f[y];
while(top)pushdown(hep[top--]);
while(get(x)){
y=f[x],top=f[y];
if(get(y))
rotate((ch[y][]==x)^(ch[top][]==y)?x:y);
rotate(x);
}pushup(x);return;
}
inline void Access(int x){
for(register int y=;x;x=f[y=x])
Splay(x),ch[x][]=y,pushup(x);
}
inline void makeroot(int x){
Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
Access(x);Splay(x);
while(ch[x][])pushdown(x),x=ch[x][];
return x;
}
inline void split(int x,int y){
makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
split(x,y);
if(findroot(y)==x&&f[x]==y&&!ch[x][]){
f[x]=ch[y][]=;pushup(y);
}return;
}
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 3e5 + ;
int f[N],v[N],s[N],r[N],hep[N],ch[N][];
inline int get(int x){
return ch[f[x]][]==x||ch[f[x]][]==x;
}
inline void pushup(int x){
s[x]=s[ch[x][]]^s[ch[x][]]^v[x];
}
inline void filp(int x){
swap(ch[x][],ch[x][]);r[x]^=;
}
inline void pushdown(int x){
if(!r[x])return;r[x]=;
if(ch[x][])filp(ch[x][]);
if(ch[x][])filp(ch[x][]);
}
inline void rotate(int x){
int y=f[x],z=f[y],k=ch[y][]==x,v=ch[x][!k];
if(get(y))ch[z][ch[z][]==y]=x;ch[x][!k]=y,ch[y][k]=v;
if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
int y=x,top=;hep[++top]=y;
while(get(y))hep[++top]=y=f[y];
while(top)pushdown(hep[top--]);
while(get(x)){
y=f[x],top=f[y];
if(get(y))
rotate((ch[y][]==x)^(ch[top][]==y)?x:y);
rotate(x);
}pushup(x);return;
}
inline void Access(int x){
for(register int y=;x;x=f[y=x])
Splay(x),ch[x][]=y,pushup(x);
}
inline void makeroot(int x){
Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
Access(x);Splay(x);
while(ch[x][])pushdown(x),x=ch[x][];
return x;
}
inline void split(int x,int y){
makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
split(x,y);
if(findroot(y)==x&&f[x]==y&&!ch[x][]){
f[x]=ch[y][]=;pushup(y);
}return;
}
int n, m, op, x, y;
int main() {
scanf("%d %d", &n, &m);
for (int i = ; i <= n; ++i) scanf("%d", &v[i]);
for (int i = ; i <= m; ++i) {
scanf("%d %d %d", &op, &x, &y);
if(op == ) split(x, y), printf("%d\n", s[y]);
else if(op == ) link(x, y);
else if(op == ) cut(x, y);
else Splay(x), v[x] = y;
}
return ;
}
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e4 + ;
int f[N], r[N],hep[N],ch[N][];
inline int get(int x){
return ch[f[x]][]==x||ch[f[x]][]==x;
}
inline void pushup(int x){
return ;
}
inline void filp(int x){
swap(ch[x][],ch[x][]);r[x]^=;
}
inline void pushdown(int x){
if(!r[x])return;r[x]=;
if(ch[x][])filp(ch[x][]);
if(ch[x][])filp(ch[x][]);
}
inline void rotate(int x){
int y=f[x],z=f[y],k=ch[y][]==x,v=ch[x][!k];
if(get(y))ch[z][ch[z][]==y]=x;ch[x][!k]=y,ch[y][k]=v;
if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
int y=x,top=;hep[++top]=y;
while(get(y))hep[++top]=y=f[y];
while(top)pushdown(hep[top--]);
while(get(x)){
y=f[x],top=f[y];
if(get(y))
rotate((ch[y][]==x)^(ch[top][]==y)?x:y);
rotate(x);
}pushup(x);return;
}
inline void Access(int x){
for(register int y=;x;x=f[y=x])
Splay(x),ch[x][]=y,pushup(x);
}
inline void makeroot(int x){
Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
Access(x);Splay(x);
while(ch[x][])pushdown(x),x=ch[x][];
return x;
}
inline void split(int x,int y){
makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
split(x,y);
if(findroot(y)==x&&f[x]==y&&!ch[x][]){
f[x]=ch[y][]=;pushup(y);
}return;
}
char op[];
int n, m, u, v;
int main() {
scanf("%d", &n);
scanf("%d", &m);
for (int i = ; i <= m; ++i) {
scanf("%s %d %d", op, &u, &v);
if(op[] == 'C') link(u, v);
else if(op[] == 'D') cut(u, v);
else {
makeroot(u);
if(findroot(v) != u) printf("No\n");
else printf("Yes\n");
}
}
return ;
}
思路:注意cut和普通的cut不一样
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 3e5 + ;
int f[N],v[N],mx[N],r[N],add[N], hep[N],ch[N][];
inline int get(int x){
return ch[f[x]][]==x||ch[f[x]][]==x;
}
inline void pushup(int x){
mx[x]= max(max(mx[ch[x][]], mx[ch[x][]]), v[x]);
}
inline void filp(int x){
swap(ch[x][],ch[x][]);r[x]^=;
}
inline void pushdown(int x){
int ls = ch[x][], rs = ch[x][];
if(r[x]) {
if(ls) filp(ls);
if(rs) filp(rs);
r[x] = ;
}
if(add[x]) {
if(ls) add[ls] += add[x], v[ls] += add[x], mx[ls] += add[x];
if(rs) add[rs] += add[x], v[rs] += add[x], mx[rs] += add[x];
add[x] = ;
}
}
inline void rotate(int x){
int y=f[x],z=f[y],k=ch[y][]==x,v=ch[x][!k];
if(get(y))ch[z][ch[z][]==y]=x;ch[x][!k]=y,ch[y][k]=v;
if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
int y=x,top=;hep[++top]=y;
while(get(y))hep[++top]=y=f[y];
while(top)pushdown(hep[top--]);
while(get(x)){
y=f[x],top=f[y];
if(get(y))
rotate((ch[y][]==x)^(ch[top][]==y)?x:y);
rotate(x);
}pushup(x);return;
}
inline void Access(int x){
for(register int y=;x;x=f[y=x])
Splay(x),ch[x][]=y,pushup(x);
}
inline void makeroot(int x){
Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
Access(x);Splay(x);
while(ch[x][])pushdown(x),x=ch[x][];
return x;
}
inline void ADD(int x,int y, int w){
makeroot(x);Access(y);Splay(y);
v[y] += w, add[y] += w, mx[y] += w;
}
inline void split(int x,int y){
makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
makeroot(x); if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y) {
split(x,y);
ch[y][] = f[ch[y][]] = ;
}
int op, x, y, w, n, m;
int U[N], V[N];
int main() {
while(~scanf("%d", &n)) {
mx[] = INT_MIN;
for (int i = ; i < n; ++i) scanf("%d %d", &U[i], &V[i]);
for (int i = ; i <= n; ++i) scanf("%d", &v[i]), mx[i] = v[i], add[i] = r[i] = ch[i][] = ch[i][] = f[i] = ;
for (int i = ; i < n; ++i) link(U[i], V[i]);
scanf("%d", &m);
for (int i = ; i <= m; ++i) {
scanf("%d", &op);
if(op == ) {
scanf("%d %d", &x, &y);
if(findroot(x) == findroot(y)) printf("-1\n");
else link(x, y);
}
else if(op == ){
scanf("%d %d", &x, &y);
if(findroot(x) != findroot(y) || x == y) printf("-1\n");
else cut(x, y);
}
else if(op == ) {
scanf("%d %d %d", &w, &x, &y);
if(findroot(x) != findroot(y)) printf("-1\n");
else ADD(x, y, w);
}
else {
scanf("%d %d", &x, &y);
if(findroot(x) != findroot(y)) printf("-1\n");
else split(x, y), printf("%d\n", mx[y]);
}
}
printf("\n");
}
return ;
}
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 1e5 + ;
int f[N],v[N],mx[N],r[N],hep[N],ch[N][];
inline int get(int x){
return ch[f[x]][]==x||ch[f[x]][]==x;
}
inline void pushup(int x){
mx[x] = max(max(mx[ch[x][]], mx[ch[x][]]), v[x]);
}
inline void filp(int x){
swap(ch[x][],ch[x][]);r[x]^=;
}
inline void pushdown(int x){
if(!r[x])return;r[x]=;
if(ch[x][])filp(ch[x][]);
if(ch[x][])filp(ch[x][]);
}
inline void Rotate(int x){
int y=f[x],z=f[y],k=ch[y][]==x,v=ch[x][!k];
if(get(y))ch[z][ch[z][]==y]=x;ch[x][!k]=y,ch[y][k]=v;
if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
int y=x,top=;hep[++top]=y;
while(get(y))hep[++top]=y=f[y];
while(top)pushdown(hep[top--]);
while(get(x)){
y=f[x],top=f[y];
if(get(y))
Rotate((ch[y][]==x)^(ch[top][]==y)?x:y);
Rotate(x);
}pushup(x);return;
}
inline void Access(int x){
for(int y=;x;x=f[y=x])
Splay(x),ch[x][]=y,pushup(x);
}
inline void makeroot(int x){
Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
Access(x);Splay(x);
while(ch[x][])pushdown(x),x=ch[x][];
return x;
}
inline void split(int x,int y){
makeroot(x);Access(y);Splay(y);
}
inline void link(int x,int y){
makeroot(x);if(findroot(y)!=x)f[x]=y;
}
inline void cut(int x,int y){
split(x,y);
if(findroot(y)==x&&f[x]==y&&!ch[x][]){
f[x]=ch[y][]=;pushup(y);
}return;
}
int n, m, x, y;
char op[];
int main() {
mx[] = INT_MIN;
scanf("%d", &n);
for (int i = ; i < n; ++i) scanf("%d%d", &x, &y), link(x, y);
scanf("%d", &m);
for (int i = ; i <= m; ++i) {
scanf("%s%d%d", op, &x, &y);
if(op[] == 'I') Splay(x), v[x] += y;
else split(x, y), printf("%d\n", mx[y]);
}
return ;
}
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdi pair<double, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head const int N = 3e4 + ;
int f[N],s[N], v[N],r[N],hep[N],ch[N][];
inline int get(int x){
return ch[f[x]][]==x||ch[f[x]][]==x;
}
inline void pushup(int x){
s[x] = s[ch[x][]] + s[ch[x][]] + v[x];
}
inline void filp(int x){
swap(ch[x][],ch[x][]);r[x]^=;
}
inline void pushdown(int x){
if(!r[x])return;r[x]=;
if(ch[x][])filp(ch[x][]);
if(ch[x][])filp(ch[x][]);
}
inline void rotate(int x){
int y=f[x],z=f[y],k=ch[y][]==x,v=ch[x][!k];
if(get(y))ch[z][ch[z][]==y]=x;ch[x][!k]=y,ch[y][k]=v;
if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x);
}
inline void Splay(int x){
int y=x,top=;hep[++top]=y;
while(get(y))hep[++top]=y=f[y];
while(top)pushdown(hep[top--]);
while(get(x)){
y=f[x],top=f[y];
if(get(y))
rotate((ch[y][]==x)^(ch[top][]==y)?x:y);
rotate(x);
}pushup(x);return;
}
inline void Access(int x){
for(register int y=;x;x=f[y=x])
Splay(x),ch[x][]=y,pushup(x);
}
inline void makeroot(int x){
Access(x);Splay(x);filp(x);
}
inline int findroot(int x){
Access(x);Splay(x);
while(ch[x][])pushdown(x),x=ch[x][];
return x;
}
inline void split(int x,int y){
makeroot(x);Access(y);Splay(y);
}
inline bool link(int x,int y){
makeroot(x);if(findroot(y)!=x)f[x]=y; else return false;
return true;
}
inline void cut(int x,int y){
split(x,y);
if(findroot(y)==x&&f[x]==y&&!ch[x][]){
f[x]=ch[y][]=;pushup(y);
}return;
}
int n, m, x, y;
char op[];
int main() {
scanf("%d", &n);
for (int i = ; i <= n; ++i) scanf("%d", &v[i]);
scanf("%d", &m);
for (int i = ; i <= m; ++i) {
scanf("%s %d %d", op, &x, &y);
if(op[] == 'b') {
if(link(x, y)) printf("yes\n");
else printf("no\n");
}
else if(op[] == 'p') {
Splay(x);
v[x] = y;
}
else {
if(findroot(x) != findroot(y)) printf("impossible\n");
else split(x, y), printf("%d\n", s[y]); }
}
return ;
}
FHQ Treap
参考:https://blog.csdn.net/pengwill97/article/details/82891241
模板:
struct fhq_treap {
static const int N = 1e5 + ;
struct Node {
int val, key, lc, rc, sz;
}tree[N];
int rt, tot;
inline void init() {
rt = tot = ;
tree[rt].sz = tree[rt].val = tree[rt].lc = tree[rt].rc = ;
srand(time());
}
inline void update(int rt) {
tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + ;
}
void split(int rt, int &a, int &b, int val) {
if(rt == ) {a = b = ; return ;}
if(tree[rt].val <= val) {
a = rt;
split(tree[rt].rc, tree[a].rc, b, val);
}
else {
b = rt;
split(tree[rt].lc, a, tree[b].lc, val);
}
update(rt);
}
void merge(int &rt, int a, int b) {
if(a== || b==) {
rt = a+b;
return ;
}
if(tree[a].key < tree[b].key) {
rt = a;
merge(tree[rt].rc, tree[a].rc, b);
}
else {
rt = b;
merge(tree[rt].lc, a, tree[b].lc);
}
update(rt);
}
inline int new_node(int val) {
tree[++tot].sz = ;
tree[tot].val = val;
tree[tot].lc = tree[tot].rc = ;
tree[tot].key = rand()*rand();
return tot;
}
void ins(int &rt, int val) {
int x = , y = , node = new_node(val);
split(rt, x, y, val);
merge(x, x, node);
merge(rt, x, y);
}
void delete_node(int &rt, int val) {
int x = , y = , z = ;
split(rt, x, y, val);
split(x, x, z, val-);
merge(z, tree[z].lc, tree[z].rc);
merge(x, x, z);
merge(rt, x, y);
}
inline int get_kth(int rt, int k) {
while(tree[tree[rt].lc].sz+ != k) {
if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc;
else k -= tree[tree[rt].lc].sz+, rt = tree[rt].rc;
}
return tree[rt].val;
}
int get_rnk(int &rt, int val) {
int x = , y = ;
split(rt, x, y, val-);
int tmp = tree[x].sz+;
merge(rt, x, y);
return tmp;
}
int get_pre(int &rt, int val) {
int x = , y = ;
split(rt, x, y, val-);
int tmp = get_kth(x, tree[x].sz);
merge(rt, x, y);
return tmp;
}
int get_scc(int &rt, int val) {
int x = , y = ;
split(rt, x, y, val);
int tmp = get_kth(y, );
merge(rt, x, y);
return tmp;
}
}t;
例题:
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define y1 y11
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb emplace_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define pdd pair<double, double>
#define mem(a, b) memset(a, b, sizeof(a))
#define debug(x) cerr << #x << " = " << x << "\n";
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//head struct fhq_treap {
static const int N = 1e5 + ;
struct Node {
int val, key, lc, rc, sz;
}tree[N];
int rt, tot;
inline void init() {
rt = tot = ;
tree[rt].sz = tree[rt].val = tree[rt].lc = tree[rt].rc = ;
srand(time());
}
inline void update(int rt) {
tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + ;
}
void split(int rt, int &a, int &b, int val) {
if(rt == ) {a = b = ; return ;}
if(tree[rt].val <= val) {
a = rt;
split(tree[rt].rc, tree[a].rc, b, val);
}
else {
b = rt;
split(tree[rt].lc, a, tree[b].lc, val);
}
update(rt);
}
void merge(int &rt, int a, int b) {
if(a== || b==) {
rt = a+b;
return ;
}
if(tree[a].key < tree[b].key) {
rt = a;
merge(tree[rt].rc, tree[a].rc, b);
}
else {
rt = b;
merge(tree[rt].lc, a, tree[b].lc);
}
update(rt);
}
inline int new_node(int val) {
tree[++tot].sz = ;
tree[tot].val = val;
tree[tot].lc = tree[tot].rc = ;
tree[tot].key = rand()*rand();
return tot;
}
void ins(int &rt, int val) {
int x = , y = , node = new_node(val);
split(rt, x, y, val);
merge(x, x, node);
merge(rt, x, y);
}
void delete_node(int &rt, int val) {
int x = , y = , z = ;
split(rt, x, y, val);
split(x, x, z, val-);
merge(z, tree[z].lc, tree[z].rc);///???
merge(x, x, z);
merge(rt, x, y);
}
inline int get_kth(int rt, int k) {
while(tree[tree[rt].lc].sz+ != k) {
if(tree[tree[rt].lc].sz >= k) rt = tree[rt].lc;
else k -= tree[tree[rt].lc].sz+, rt = tree[rt].rc;
}
return tree[rt].val;
}
int get_rnk(int &rt, int val) {
int x = , y = ;
split(rt, x, y, val-);
int tmp = tree[x].sz+;
merge(rt, x, y);
return tmp;
}
int get_pre(int &rt, int val) {
int x = , y = ;
split(rt, x, y, val-);
int tmp = get_kth(x, tree[x].sz);
merge(rt, x, y);
return tmp;
}
int get_scc(int &rt, int val) {
int x = , y = ;
split(rt, x, y, val);
int tmp = get_kth(y, );
merge(rt, x, y);
return tmp;
}
}t;
int n, op, x;
int main() {
t.init();
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
scanf("%d %d", &op, &x);
if(op == ) t.ins(t.rt, x);
else if(op == ) t.delete_node(t.rt, x);
else if(op == ) printf("%d\n", t.get_rnk(t.rt, x));
else if(op == ) printf("%d\n", t.get_kth(t.rt, x));
else if(op == ) printf("%d\n", t.get_pre(t.rt, x));
else printf("%d\n", t.get_scc(t.rt, x));
}
return ;
}
算法笔记--Splay && Link-Cut-Tree的更多相关文章
- 学习笔记:Link Cut Tree
模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...
- link cut tree 入门
鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- Link Cut Tree学习笔记
从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...
- Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题
A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...
- Link/cut Tree
Link/cut Tree 一棵link/cut tree是一种用以表示一个森林,一个有根树集合的数据结构.它提供以下操作: 向森林中加入一棵只有一个点的树. 将一个点及其子树从其所在的树上断开. 将 ...
- 洛谷P3690 Link Cut Tree (模板)
Link Cut Tree 刚开始写了个指针版..调了一天然后放弃了.. 最后还是学了黄学长的板子!! #include <bits/stdc++.h> #define INF 0x3f3 ...
- bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门
link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
随机推荐
- linux基本命令之stat
我们在开始接触到linux系统时一般会首先接触ls命令,但是ls命令一来有众多参数,二来所能显示的文件描述也极为有限,仅仅是stat的一部分,那么我们来看下我们的stat命令如图 stat /etc ...
- 从网卡发送数据再谈TCP/IP协议—网络传输速度计算-网卡构造
在<在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP>里面提到 单个TCP包每次打包1448字节的数据进行发送(以太网Ethernet最大的数据帧是1518字节,以 ...
- webstorm编辑器使用
1.自动生成vue文件模板,如图
- Kindle:自动追更之发送邮件
@echo off setlocal enabledelayedexpansion set from=Kindlekindle设置好信任的邮箱set pw=密码 set to=Kindle邮箱 cd ...
- web开发前端面试知识点目录整理
web开发前端面试知识点目录整理 基本功考察 关于Html 1. html语义化标签的理解; 结构化的理解; 能否写出简洁的html结构; SEO优化 2. h5中新增的属性; 如自定义属性data, ...
- ansible-2.1.0.0_module
ansible --version ansible 2.1.0.0 config file = /home/onest/luoliyu/ceph-ansible/ansible.cfg configu ...
- 叮咚,你的Lauce上线了!
哈,2014 - 2016 - 2018,虽然每隔两年才有那么一篇随笔,博客园,我还是爱你的~ 嗯,2018,马上又要失业了,我这是自带黑属性啊啊啊哈,工作了4年多的项目要被砍掉了, 倒不是说非要这个 ...
- 使用aspx 直接生成excel
<%@ Page Language="C#" EnableEventValidation="false" ResponseEncoding="g ...
- self sqflite sample =======================
import 'package:path_provider/path_provider.dart'; import 'dart:async'; import 'package:flutter/mate ...
- Laravel5.5学习笔记
安装composer 下载安装脚本 php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php ...