ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P4719 【模板】动态 DP (LCT版)

2021-07-07 16:57:55  阅读:178  来源: 互联网

标签:tmp LCT ch old int luogu rson maxn P4719


方法二:LCT+矩阵乘法
上文中,我们用线段树来维护重链上的各种矩阵转移.

第二种方法是将树链剖分替换为动态树.
我们知道,矩阵乘法 $\begin{bmatrix} F_{u,0} & F_{u,0}\\ F_{u,1}  & -\infty \end{bmatrix}\times\begin{bmatrix} F_{i,0}\\F_{i,1} \end{bmatrix}=\begin{bmatrix} F_{u,0}\\F_{u,1} \end{bmatrix}$ 中第一个矩阵中的每一个 $F_{u,k}$ 都是指考虑轻链时 $u$ 的 DP 值.
在 $LCT$ 中,树的轻重路径是交替变换的.
我们用维护子树信息的方式维护即可.
即设 $tmp$ 矩阵表示该点虚儿子的所有 DP 值的贡献(只是不包括重儿子).
再设 $t$ 矩阵维护 $Splay$ 中的转移.
具体细节看看代码:  

Code:

// luogu-judger-enable-o2
//Dynamic DP with LCT 
#include<bits/stdc++.h>
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin)  
#define maxn 100002 
#define inf 100000000 
using namespace std; 
//Link cut tree
void de()
{
    printf("ok\n"); 
}
namespace LCT
{     

    struct Matrix
    {
        ll a[2][2];
        ll*operator[](int x){ return a[x];}    
    }t[maxn],tmp[maxn];  
    Matrix operator*(Matrix a,Matrix b)
    {
    	Matrix c;
    	c[0][0]=max(a[0][0]+b[0][0],a[0][1]+b[1][0]); 
    	c[0][1]=max(a[0][0]+b[0][1],a[0][1]+b[1][1]); 
    	c[1][0]=max(a[1][0]+b[0][0],a[1][1]+b[1][0]); 
    	c[1][1]=max(a[1][0]+b[0][1],a[1][1]+b[1][1]); 
    	return c; 
    }

    //tmp :: 虚儿子信息 
    //t :: 树剖实际转移矩阵 
    #define lson ch[x][0]
    #define rson ch[x][1] 
    int ch[maxn][2],f[maxn]; 
    int isRoot(int x) 
    {	
        return !(ch[f[x]][0]==x || ch[f[x]][1]==x);  
    }
    int get(int x) 
    { 
        return ch[f[x]][1]==x; 
    } 
    void pushup(int x)
    { 
        t[x]=tmp[x]; 
        if(lson) t[x]=t[lson]*t[x]; 
        if(rson) t[x]=t[x]*t[rson]; 
    }
    void rotate(int x)
    {
        int old=f[x],fold=f[old],which=get(x); 
        if(!isRoot(old)) ch[fold][ch[fold][1]==old]=x; 
        ch[old][which]=ch[x][which^1],f[ch[old][which]]=old; 
        ch[x][which^1]=old,f[old]=x,f[x]=fold; 
        pushup(old),pushup(x); 
    }
    void splay(int x) 
    {
        int u=x;
        while(!isRoot(u)) u=f[u];                     
        u=f[u]; 
        for(int fa;(fa=f[x])!=u;rotate(x)) 
            if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);  
    }
    void Access(int x)
    {
        for(int y=0;x;y=x,x=f[x])
        {
            splay(x); 
            if(rson) 
            {
                tmp[x][0][0]+=max(t[rson][0][0],t[rson][1][0]); 
                tmp[x][1][0]+=t[rson][0][0];     
            }
            if(y) 
            { 
                tmp[x][0][0]-=max(t[y][0][0],t[y][1][0]); 
                tmp[x][1][0]-=t[y][0][0];  
            }
            tmp[x][0][1]=tmp[x][0][0];  
            rson=y,pushup(x); 
        }
    } 
};     


//variables 
int DP[maxn][2];   
int V[maxn],hd[maxn],to[maxn<<1],nex[maxn<<1]; 
int n,Q,edges; 
void add(int u,int v){ nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;  } 


//build graph 
void dfs(int u,int ff)
{         
    LCT::f[u]=ff; 
    DP[u][0]=0;
    DP[u][1]=V[u]; 
    for(int i=hd[u];i;i=nex[i])
    {
        int v=to[i]; 
        if(v==ff) continue; 
        dfs(v,u); 
        DP[u][0]+=max(DP[v][1],DP[v][0]); 
        DP[u][1]+=DP[v][0]; 
    }            
    LCT::tmp[u]=(LCT::Matrix){ DP[u][0], DP[u][0], DP[u][1], -inf};
    LCT::t[u]=LCT::tmp[u];   
}


//主程序~ 
int main()
{
    // setIO("input");  
    scanf("%d%d",&n,&Q); 
    for(int i=1;i<=n;++i) scanf("%d",&V[i]); 
    for(int i=1,u,v;i<n;++i) 
    {
        scanf("%d%d",&u,&v); 
        add(u,v),add(v,u); 
    }
    dfs(1,0); 
    while(Q--)
    {
        int x,y; 
        scanf("%d%d",&x,&y);            
        LCT::Access(x);
        LCT::splay(x);                
        LCT::tmp[x][1][0]+=(ll)y-V[x];
        V[x]=y;        
        LCT::pushup(x);    
        LCT::splay(1); 
        printf("%lld\n",max(LCT::t[1][0][0], LCT::t[1][1][0]));       
    }
    return 0; 
}

  

   

标签:tmp,LCT,ch,old,int,luogu,rson,maxn,P4719
来源: https://blog.51cto.com/u_15291195/3004873

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有