zoukankan      html  css  js  c++  java
  • [BZOJ1984] 月下“毛景树”

    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;
            }
        }
    }
    
    
    
  • 相关阅读:
    if 语句
    变量命名
    python变量
    运算符
    注释
    PyCharm
    python版本,执行
    Tornado 【简述】
    Git 【管理篇】
    MySQL的介绍
  • 原文地址:https://www.cnblogs.com/mollnn/p/13650101.html
Copyright © 2011-2022 走看看