动态动态规划 DDP

宏定义

树链剖分

变量

  • struct Juz\texttt{struct Juz}:包含于矩阵
  • struct Segment_Tree\texttt{struct Segment\_Tree}线段树部分。
  • int f[i][0/1]\texttt{int f[i][0/1]}:不选//选节点 ii 的最大价值。
  • int dq[i]\texttt{int dq[i]}:节点 ii 的权值。
  • struct TCP\texttt{struct TCP}:同树链剖分的变量。

函数

  • Juz operator *(const Juz &x,const Juz &y)\texttt{Juz operator *(const Juz \&x,const Juz \&y)}:需要重新定义的矩阵乘法。
  • void dfs1(int p)\texttt{void dfs1(int p)}:第一次深搜。
  • int dfs2(int p,int q)\texttt{int dfs2(int p,int q)}:第二次深搜。
  • void init(int root,int n)\texttt{void init(int root,int n)}:对节点数为 nn,根节点为 rootroot 的树进行树链剖分。
  • void change1(int p,int z)\texttt{void change1(int p,int z)}:将节点 pp 的点权修改为 zzzz 是修改参数。
  • int ask1()\texttt{int ask1()}:求此时整棵树的答案。

代码

#define pl p<<1
#define pr p<<1|1
#define pf a[p].fa
#define pde a[p].dep
#define psi a[p].sze
#define pte a[p].ted
#define pdf a[p].dfn
#define pso a[p].son
#define pt a[p].top
#define pc a[p].ced
const long long inf=1e9;
struct Juz{
    long long a[3][3],h,l;
    void clean(){
        memset(a,-0x3F,sizeof a);
        h=l=0;
    }
}w[N];
Juz operator *(const Juz &x,const Juz &y){
    Juz z;
    z.clean();
    z.h=x.h;z.l=y.l;
    for(int i=1;i<=x.h;++i)
        for(int j=1;j<=y.l;++j)
            for(int k=1;k<=x.l;++k)
                z.a[i][j]=max(z.a[i][j],x.a[i][k]+y.a[k][j]);
    return z;
}
int f[N][2],dq[N];
struct Segment_Tree{
    struct Tree{
        int l,r;
        Juz val;
    }a[N*4];
    void pushup(int p){
        a[p].val=a[pl].val*a[pr].val;
    }
    void build(int p,int l,int r,int *rnk){
        a[p].l=l;
        a[p].r=r;
        if(l==r){
           a[p].val=w[rnk[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(pl,l,mid,rnk);
        build(pr,mid+1,r,rnk);
        pushup(p);
    }
    void change(int p,int x,int *rnk){
        if(a[p].l==a[p].r){
            a[p].val=w[rnk[x]];
            return;
        }
        int mid=(a[p].l+a[p].r)>>1;
        if(x<=mid)
            change(pl,x,rnk);
        if(x>mid)
            change(pr,x,rnk);
        pushup(p);
    }
    Juz ask(int p,int l,int r){
        if(l<=a[p].l&&a[p].r<=r){
            return a[p].val;
        }
        int mid=(a[p].l+a[p].r)>>1;
        if(l<=mid&&r>mid)
        	return ask(pl,l,r)*ask(pr,l,r);
        if(l<=mid)
        	return ask(pl,l,r);
        if(r>mid)
        	return ask(pr,l,r);
    }
}tree;
struct TCP{
    struct Node{
        int fa,dep,dfn;//self
        int sze,ted;//tree
        int son,top,ced;//chain
    }a[N];
    int cnt,rnk[N];
    void dfs1(int p){
        pso=-1;
        psi=1;
        for(int i=head[p];i;i=nxt[i]){
            int y=ver[i];
            if(!a[y].dep){
                a[y].dep=pde+1;
                a[y].fa=p;
                dfs1(y);
                psi+=a[y].sze;
                if(pso==-1||a[y].sze>a[pso].sze)
                    pso=y;
            }
        }
    }
    int dfs2(int p,int q){
        pt=q;
        pdf=++cnt;
        rnk[cnt]=pte=p;
        /*make*/
		f[p][0]=0;f[p][1]=dq[p];
        w[p].h=w[p].l=2;
        w[p].a[1][1]=w[p].a[1][2]=0;
        w[p].a[2][1]=dq[p];
        bool yu=0;
        if(pso==-1){
            int ted=pte;
            pc=cnt;
            while(p!=q){
                p=pf;
                pc=cnt;
            }
            yu=1;
            return ted;
        }
        pte=dfs2(pso,q);
        /*update*/
        f[p][0]+=max(f[pso][0],f[pso][1]);
        f[p][1]+=f[pso][0];
        for(int i=head[p];i;i=nxt[i]){
            int y=ver[i];
            if(y==pso||y==pf)
            	continue;
            pte=dfs2(y,y);
            /*update*/
            f[p][0]+=max(f[y][0],f[y][1]);
            f[p][1]+=f[y][0];
            w[p].a[1][1]+=max(f[y][0],f[y][1]);
            w[p].a[1][2]=w[p].a[1][1];
            w[p].a[2][1]+=f[y][0];
        }
        return pte;
    }
    void init(int root,int n){
        cnt=0;
        a[root].dep=1;
        dfs1(root);
        dfs2(root,root);
        tree.build(1,1,n,rnk);
    }
    void change1(int p,int z){
    	w[p].a[2][1]+=z-dq[p];
    	dq[p]=z;
        Juz x,y;
        while(p){
        	x=tree.ask(1,a[pt].dfn,pc);
        	tree.change(1,pdf,rnk); 
        	y=tree.ask(1,a[pt].dfn,pc);
        	p=pt;p=pf;
        	/*merge*/
        	w[p].a[1][1]+=max(y.a[1][1],y.a[2][1])-max(x.a[1][1],x.a[2][1]);
        	w[p].a[1][2]=w[p].a[1][1];
        	w[p].a[2][1]+=y.a[1][1]-x.a[1][1];
		}
    }
    int ask1(){
    	Juz an=tree.ask(1,1,a[1].ced);
        return max(an.a[1][1],an.a[2][1]);
    }
}tr;
posted @ 2022-11-23 13:25  luckydrawbox  阅读(9)  评论(0)    收藏  举报  来源