题解
题面
左偏树练习题吧
改权值的操作就是把这个点扯出来, 左右儿子合并后接到这个点的父亲上去, 然后再把这个点重新塞进左偏树里就行了
至于这部操作为什么不要更新 dis , 可能是因为 dis 最多只会变 1 , 左偏的性质还是存在吧
Code
#include
#include
#include
#include
const int N = 300005;
using namespace std;
int n, m, T, rt[505];
char s[105];
struct node
{
int val, dis, fa, ch[2];
} t[N];
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
int merge(int x, int y)
{
if(!x || !y) return x + y;
if(t[x].val > t[y].val) swap(x, y);
t[x].ch[1] = merge(t[x].ch[1], y);
if(t[t[x].ch[1]].dis > t[t[x].ch[0]].dis) swap(t[x].ch[0], t[x].ch[1]);
t[x].dis = t[t[x].ch[1]].dis + 1;
t[t[x].ch[0]].fa = t[t[x].ch[1]].fa = x;
return x;
}
void modify(int x, int y, int z)
{
int f = t[y].fa, tmp = merge(t[y].ch[0], t[y].ch[1]);
if(rt[x] == y) rt[x] = tmp;
else t[f].ch[t[f].ch[1] == y] = tmp;
t[tmp].fa = f; t[y].val = z, t[y].fa = 0;
t[y].ch[0] = t[y].ch[1] = 0;
rt[x] = merge(rt[x], y);
}
int main()
{
n = read (), m = read (), T = read ();
int x, y, z;
while(T--)
{
scanf("%s", s + 1);
if(s[1] == 'A')
{
x = read (), y = read (), z = read ();
modify(x, y, z);
// t[y].val = z, rt[x] = merge(rt[x], y);
}
else if(s[1] == 'D')
{
x = read (), y = read (), z = read ();
modify(x, y, t[y].val - z);
}
else if(s[1] == 'T')
{
x = read (), y = read ();
rt[y] = merge(rt[y], rt[x]), rt[x] = 0;
}
else if(s[1] == 'M')
x = read (), printf("%d\n", t[rt[x]].val);
else if(s[1] == 'W')
{
x = read (), y = read ();
if((t[rt[x]].ch[0] && t[rt[x]].val == t[t[rt[x]].ch[0]].val) || (t[rt[x]].ch[1] && t[rt[x]].val == t[t[rt[x]].ch[1]].val))
puts("ERROR");
else modify(x, rt[x], t[rt[x]].val + y);
}
}
return 0;
}