Description

给定一棵树,每根树枝上有权值表示树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

Solution

边权 LCT + 懒标记

所有 x>n 的点是虚点,它们不贡献 siz

这样在打标记时,p>n 的点不会获得 val,同时若 splay 中子树的 siz=0 则不会被标记修改

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000000;

int n,m,val[N];

namespace lct
{
int top, q[N], ch[N][2], fa[N], rev[N];
int a[N], tag[N], siz[N], cov[N];
inline void pushup(int x)
{
    a[0] = tag[0] = cov[0] = siz[0] = 0;
    a[x] = max(val[x], max(a[ch[x][0]], a[ch[x][1]]));
    siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + (x>n);
}
void add(int p,int v)
{
    if(!p) return;
    if(p>n) val[p] += v;
    if(siz[p]) a[p] += v;
    if(siz[p]) tag[p] += v;
}
void cover(int p,int v)
{
    if(!p) return;
    tag[p]=0;
    if(p>n) val[p]=v;
    if(siz[p]) a[p]=v;
    if(siz[p]) cov[p]=v;
}
inline void pushdown(int x)
{
    if(rev[x])
    {
        rev[ch[x][0]]^=1;
        rev[ch[x][1]]^=1;
        rev[x]^=1;
        swap(ch[x][0],ch[x][1]);
    }
    if(cov[x])
    {
        cover(ch[x][0],cov[x]);
        cover(ch[x][1],cov[x]);
        cov[x]=0;
    }
    if(tag[x])
    {
        add(ch[x][0],tag[x]);
        add(ch[x][1],tag[x]);
        tag[x]=0;
    }
}
inline bool isroot(int x)
{
    return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x;
}
inline void rotate(int p)
{
    int q=fa[p], y=fa[q], x=ch[fa[p]][1]==p;
    ch[q][x]=ch[p][x^1];
    fa[ch[q][x]]=q;
    ch[p][x^1]=q;
    fa[q]=p;
    fa[p]=y;
    if(y) if(ch[y][0]==q) ch[y][0]=p;
        else  if(ch[y][1]==q) ch[y][1]=p;
    pushup(q);
    pushup(p);
}
inline void splay(int x)
{
    q[top=1]=x;
    for(int i=x; !isroot(i); i=fa[i]) q[++top]=fa[i];
    for(int i=top; i; i--) pushdown(q[i]);
    for(; !isroot(x); rotate(x))
        if(!isroot(fa[x]))
            rotate((ch[fa[x]][0]==x)==(ch[fa[fa[x]]][0]==fa[x])?fa[x]:x);
}
void access(int x)
{
    for(int t=0; x; t=x,x=fa[x])
        splay(x),ch[x][1]=t,pushup(x);
}
void makeroot(int x)
{
    access(x);
    splay(x);
    rev[x]^=1;
}
int find(int x)
{
    access(x);
    splay(x);
    while(ch[x][0]) x=ch[x][0];
    return x;
}
void split(int x,int y)
{
    makeroot(x);
    access(y);
    splay(y);
}
void cut(int x,int y)
{
    split(x,y);
    if(ch[y][0]==x)
        ch[y][0]=0, fa[x]=0;
}
void link(int x,int y)
{
    makeroot(x);
    fa[x]=y;
    pushup(y);
}
int query(int x,int y)
{
    split(x,y);
    return a[y];
}
void modify_a(int u,int v,int w)
{
    split(u,v);
    add(v,w);
}
void modify_c(int u,int v,int w)
{
    split(u,v);
    cover(v,w);
}
}

struct str_edge
{
    int u,v,w;
} edge[N];

signed main()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
        int u,v,w;
        cin>>u>>v>>w;
        val[i+n]=w;
        lct::link(u,i+n);
        lct::link(v,i+n);
        edge[i]={u,v,w};
    }
    while(true)
    {
        string str;
        cin>>str;
        if(str=="Add")
        {
            int u,v,w;
            cin>>u>>v>>w;
            lct::modify_a(u,v,w);
        }
        if(str=="Cover")
        {
            int u,v,w;
            cin>>u>>v>>w;
            lct::modify_c(u,v,w);
        }
        if(str=="Change")
        {
            int id,w;
            cin>>id>>w;
            lct::modify_c(edge[id].u,edge[id].v,w);
        }
        if(str=="Max")
        {
            int u,v;
            cin>>u>>v;
            cout<<lct::query(u,v)<<endl;
        }
        if(str=="Stop")
        {
            break;
        }
    }
}


相关文章:

  • 2021-07-06
  • 2021-11-16
  • 2021-12-12
  • 2022-12-23
  • 2021-08-18
  • 2021-06-19
  • 2022-01-08
猜你喜欢
  • 2022-03-09
  • 2022-12-23
  • 2022-12-23
  • 2021-09-18
  • 2022-12-23
  • 2021-12-27
  • 2021-07-16
相关资源
相似解决方案