P
a
r
t
0
Part_0
Part0:吐槽 我错了,这种毒瘤题真的不适合我这种退役狗 表示被负数坑死了
P
a
r
t
1
Part_1
Part1:思路 开两个左偏树:
H
1
H_1
H1维护
N
N
N个节点,
H
2
H_2
H2维护
H
1
H_1
H1堆顶元素
U
U
U:
H
1
H_1
H1直接连边,
H
2
H_2
H2删去一个点 (先判断是否在同一堆中)
A
1
A_1
A1:
H
1
H_1
H1—将
x
x
x点取出来,加上
v
v
v后再合并上去 (要加上
l
a
z
y
lazy
lazy未下传的值)
H
2
H_2
H2—将
H
1
H_1
H1的原堆顶取出,再将新堆顶合并
A
2
A_2
A2:
H
1
H_1
H1打标记,
H
2
H_2
H2同于
A
1
A_1
A1中
H
1
H_1
H1的操作
A
3
A_3
A3:直接一个变量记录即可
F
1
F_1
F1:直接在
H
1
H_1
H1中查询(同上要加上
l
a
z
y
lazy
lazy的值)
F
2
F_2
F2:
H
1
H_1
H1堆顶
F
3
F_3
F3:
H
2
H_2
H2堆顶 PS:貌似可以用并查集优化,但是已经码得心累了,
G
i
v
e
Give
Give
U
p
Up
Up
P
a
r
t
2
Part_2
Part2:左偏树涉及操作 初始化、合并、删除(已知节点)
代码
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>#define IL inlineusingnamespace std;
IL intread(){int sum =0;bool f =0;char c =getchar();for(;'0'> c || c >'9'; c =getchar())if(c =='-') f =1;for(;'0'<= c && c <='9'; c =getchar())
sum = sum *10+(c -'0');return f ?-sum : sum;}constintN(300005);
queue<int>Q;struct zps
{int ch[N][2], pa[N], val[N], dis[N], lazy[N];
IL intGet_val(int x){int s = val[x];for(x = pa[x]; x; x = pa[x]) s += lazy[x];return s;}
IL intFind(int x){for(; pa[x]; x = pa[x]);return x;}
IL voidClean(int x){if(!lazy[x])return;int y;if((y = ch[x][0])){ val[y]+= lazy[x]; lazy[y]+= lazy[x];}if((y = ch[x][1])){ val[y]+= lazy[x]; lazy[y]+= lazy[x];}
lazy[x]=0;}
IL intMerge(int x,int y){if(!x)return y;if(!y)return x;if(val[x]< val[y])swap(x, y);Clean(x);
ch[x][1]=Merge(ch[x][1], y);
pa[ch[x][1]]= x;if(dis[ch[x][0]]< dis[ch[x][1]])swap(ch[x][0], ch[x][1]);
dis[x]= dis[ch[x][1]]+1;return x;}
IL voidClear(int x){
pa[x]= ch[x][0]= ch[x][1]=0;}
IL intDelete(int x){Clean(x);int tmp =Merge(ch[x][0], ch[x][1]), p = pa[x];
pa[tmp]= p;if(p) ch[p][(x == ch[p][1])]= tmp;Clear(x);for(; p;){if(dis[ch[p][0]]< dis[ch[p][1]])swap(ch[p][0], ch[p][1]);if(dis[p]== dis[ch[p][1]]+1)returnFind(p);
dis[p]= dis[ch[p][1]]+1;
tmp = p;
p = pa[p];}return tmp;}
IL intAdd(int x,int v){
val[x]+= v;//没什么用的优化Clean(pa[x]);Clean(x);if(val[pa[x]]>= val[x]&& val[x]>= val[ch[x][0]]&& val[x]>= val[ch[x][1]])returnFind(x);
val[x]=Get_val(x);returnMerge(Delete(x), x);}
IL intbuild(){for(int t = Q.size(), p1, p2; t >1;--t){
p1 = Q.front(); Q.pop();
p2 = Q.front(); Q.pop();
Q.push(Merge(p1, p2));}return Q.front();}}h1, h2;intmain(){int n =read();int root2 =0;int ad4 =0;for(int i =1; i <= n;++i){
Q.push(i);
h2.val[i]= h1.val[i]=read();}
root2 = h2.build();char op[5]={0};for(int m =read(), x, y, tmp, tmp2; m;--m){scanf(" %s", op);if(op[0]=='U'){
x = h1.Find(read()); y = h1.Find(read());if(x == y)continue;
root2 = h2.Delete((h1.Merge(x, y)== x ? y : x));}elseif(op[0]=='A'&& op[1]=='1'){
x =read(); y =read();
tmp = h1.Find(x);/*root2 = h2.Delete(tmp);
tmp = h1.Add(x, y);
h2.val[tmp] = h1.val[tmp];
root2 = h2.Merge(root2, tmp);*///没什么用的优化
tmp2 = h1.Add(x, y);if(tmp ^ tmp2){
root2 = h2.Delete(tmp);
h2.val[tmp2]= h1.val[tmp2];
root2 = h2.Merge(root2, tmp2);}elseif(x == tmp){
root2 = h2.Add(x, y);}}elseif(op[0]=='A'&& op[1]=='2'){
x = h1.Find(read()); y =read();
h1.val[x]+= y; h1.lazy[x]+= y;
root2 = h2.Add(x, y);}elseif(op[0]=='A'&& op[1]=='3'){
ad4 +=read();}elseif(op[0]=='F'&& op[1]=='1'){
tmp = h1.Get_val(read())+ ad4;printf("%d\n", tmp);}elseif(op[0]=='F'&& op[1]=='2'){
x = h1.Find(read());printf("%d\n", h1.val[x]+ ad4);}elseif(op[0]=='F'&& op[1]=='3'){printf("%d\n", h2.val[root2]+ ad4);}}return0;}