终于调过了,决定把这份巨屎无比的冗长代码贴上来
解题思路:
主要在于发现两个题目的性质:
1.对于插入操作,插入的元素只可能作为他前驱的右儿子或者后继的左儿子
2.旋转最大最小值,并不会改变树的结构,实质上就是把要删除的那个元素直接提到根节点(模拟即可证明)
有了这两条性质,我们可以发现只需要维护这棵树的形态并能够在log内的复杂度求树上某个点的深度
于是我们就可以想到用LCT(有删除操作)。
恰好LCT又是以深度为key值建树,所以我们只需要再维护原树的父子关系,便于LCT的link-cut,这个可以用set维护(找前驱后继),然后每次相当于询问每个点到根节点的距离,又变成模板了
代码细节很多,还要注意这是一棵有根树,还要维护根节点是谁
代码:
#include
#define ll long long
#define mm(a, b) memset(a, b, sizeof(a))
#define For(i, a, b) for(int i = (a);i <= (b); ++i)
#define rep(i, a, b) for(int i = (a);i >= (b); --i)
#define gnn cerr << "GNN睡着了" << endl;
using namespace std;
const int inf = 1e9 + 1;
int read(){
int sum = 0, fg = 1;
char c = getchar();
while(c < '0' || c > '9'){if(c == '-')fg = -1;c = getchar();}
while(c >='0' && c <='9')sum = (sum << 1) + (sum << 3) + c-'0', c = getchar();
return sum * fg;
}
const int maxn = 200010;
void file(){
#ifndef ONLINE_JUDGE
freopen("ai.in", "r", stdin);
freopen("ai.out", "w", stdout);
#endif
}
map<int , int> q;
int m, tree[maxn], val[maxn], ch[maxn][2], rev[maxn], cnt, fa[maxn];
bool isroot(int h){return ch[fa[h]][0] != h && ch[fa[h]][1] != h;}
void pushup(int h){tree[h] = 1; tree[h] += tree[ch[h][0]] + tree[ch[h][1]];}
void pushdown(int h){
if(!rev[h]) return;
rev[h] = 0;
swap(ch[h][0], ch[h][1]);
if(ch[h][0]) rev[ch[h][0]] ^= 1;
if(ch[h][1]) rev[ch[h][1]] ^= 1;
}
void PUSHDOWN(int h){
if(!isroot(h)) PUSHDOWN(fa[h]);
pushdown(h);
}
void rotate(int h){
int father = fa[h], grandfa = fa[father];
bool w = (ch[father][1] == h);
fa[ch[h][w^1]] = father;
ch[father][w] = ch[h][w^1];
fa[father] = h;
ch[h][w^1] = father;
fa[h] = grandfa;
if(ch[grandfa][0] == father) ch[grandfa][0] = h;
else if(ch[grandfa][1] == father) ch[grandfa][1] = h;
pushup(father), pushup(h);
}
bool pd(int h){return ch[fa[h]][0] == h;}
void splay(int h){
PUSHDOWN(h);
while(!isroot(h)){
if(!isroot(fa[h]) && pd(h) == pd(fa[h])) rotate(fa[h]);
rotate(h);
}
}
void access(int h){
int y = 0;
while(h){
splay(h);
ch[h][1] = y;
pushup(h);
y = h;
h = fa[h];
}
}
void makeroot(int h){
access(h);
splay(h);
rev[h] ^= 1;
}
void cut(int x,int y){
makeroot(x);
access(y);
splay(y);
fa[x] = ch[y][0] = 0;
}
void link(int x,int y){
makeroot(x);
fa[x] = y;
}
void Get(){
m = read();
}
int zf = 0, nowroot, truelyfa[maxn], truelych[maxn][2];
int get_dep(int h){
makeroot(nowroot);
access(h);
splay(h);
return tree[h];
}
set<int> Set;
set<int>::iterator it, other;
int nowyuansu, flag = 0;
void _Min(int type){
it = Set.begin();
int Min = *it;
int id = q[Min];
printf("%d\n", get_dep(id));
if(type == 1) nowyuansu = Min;
if(id == nowroot) {flag = 1; return;}
if(truelych[id][1]) cut(truelych[id][1], id);
if(truelyfa[id]){
cut(truelyfa[id], id);
int father = truelyfa[id];
truelych[father][0] = truelych[id][1];
if(truelych[id][1]){
truelyfa[truelych[id][1]] = father;
link(truelych[id][1], father);
}
}
truelyfa[id] = 0;
if(nowroot == id){
if(truelych[id][1]){
link(id, truelych[id][1]);
truelyfa[truelych[id][1]] = id;
}
}
else{
truelych[id][1] = nowroot;
truelyfa[nowroot] = id;
link(id, nowroot);
}
nowroot = id;
makeroot(nowroot);
}
void _Max(int type){
it = Set.end();
-- it;
int Max = *it;
int id = q[Max];
printf("%d\n", get_dep(id));
if(type == 1) nowyuansu = Max;
if(id == nowroot) {flag = 1; return;}
if(truelych[id][0]) cut(truelych[id][0], id);
if(truelyfa[id]){
cut(truelyfa[id], id);
int father = truelyfa[id];
truelych[father][1] = truelych[id][0];
if(truelych[id][0]){
truelyfa[truelych[id][0]] = father;
link(truelych[id][0], father);
}
}
truelyfa[id] = 0;
if(nowroot == id){
if(truelych[id][0]){
link(id, truelych[id][0]);
truelyfa[truelych[id][0]] = id;
}
}
else{
truelych[id][0] = nowroot;
truelyfa[nowroot] = id;
link(id, nowroot);
}
nowroot = id;
makeroot(nowroot);
}
void solve(){
while(m --){
int type = read();
if(type == 1){
int x = read();
++ cnt;
q[x] = cnt;
zf ++;
if(zf == 1) nowroot = cnt;
int pre = inf;
it = Set.lower_bound(x);
if(it != Set.begin()) --it, pre = *it;
other = Set.upper_bound(x);
int suf = inf;
if(other != Set.end()) suf = *other;
Set.insert(x);
int ans = 1;
if(pre != inf && suf != inf){
int ans1 = get_dep(q[pre]), ans2 = get_dep(q[suf]);
makeroot(nowroot);
if(get_dep(q[pre]) < get_dep(q[suf])){
fa[cnt] = q[suf];
truelyfa[cnt] = q[suf];
truelych[q[suf]][0] = cnt;
ans = ans2 + 1;
}
else{
fa[cnt] = q[pre];
truelyfa[cnt] = q[pre];
truelych[q[pre]][1] = cnt;
ans = ans1 + 1;
}
}
else if(pre != inf){
int ans1 = get_dep(q[pre]);
makeroot(nowroot);
fa[cnt] = q[pre];
truelyfa[cnt] = q[pre];
truelych[q[pre]][1] = cnt;
ans = ans1 + 1;
}
else if(suf != inf){
int ans2 = get_dep(q[suf]);
makeroot(nowroot);
fa[cnt] = q[suf];
truelyfa[cnt] = q[suf];
truelych[q[suf]][0] = cnt;
ans = ans2 + 1;
}
printf("%d\n", ans);
}
else if(type == 2){
_Min(0);
}
else if(type == 3){
_Max(0);
}
else if(type == 4){
flag = 0;
_Min(1);
if(flag && zf != 1){
cut(nowroot, truelych[nowroot][1]);
truelyfa[truelych[nowroot][1]] = 0;
nowroot = truelych[nowroot][1];
}
else if(zf != 1){
cut(nowroot, truelych[nowroot][1]);
nowroot = truelych[nowroot][1];
truelyfa[nowroot] = 0;
}
-- zf;
makeroot(nowroot);
Set.erase(nowyuansu);
}
else{
flag = 0;
_Max(1);
if(flag && zf != 1){
cut(nowroot, truelych[nowroot][0]);
truelyfa[truelych[nowroot][0]] = 0;
nowroot = truelych[nowroot][0];
}
else if(zf != 1){
cut(nowroot, truelych[nowroot][0]);
nowroot = truelych[nowroot][0];
truelyfa[nowroot] = 0;
}
--zf;
makeroot(nowroot);
Set.erase(nowyuansu);
}
}
}
int main(){
file();
Get();
solve();
return 0;
}