And dynamic dp dp dp sets

Outline

This is of particular types \ (dp \) species, respectively, with modified \ (dp \) , and \ (dp \) process itself is closely related to \ (dp \)

Dynamic dp

Outline

Some simple \ (dp \) how to do if the band to modify

If the status is an ordinary idea, a modification value, then include this in all cases will be modified, shared equally \ (O (n) \)

Administered a rough view, we can make all the states included in the amortized value, such as a doubling of trying to divide the interval, so that an equal share to be included into a number of states \ (\ log \) , but this statement is very vague, we do not know What state can be doubled

In fact, it involves a very important thing, "transfer" This operation has associativity No

If so, we can maintain a section, combined, a tree can be split into a heavy chain by a variety of equilibrium or tree treated

Many new definition matrix has associativity

Excess mention that, in the trees, just in this way they can use only \ (dp \) key points of an imaginary tree \ (dp \) alternative

problem

\ (\ mathtt {BSOJ5290} \ ) support the modification right point, a dynamic tree seeking maximum independent set

Consider the general \ (dp \)

Set \ (f_ {i, 0/ 1} \) represents \ (I \) point is not selected / selected subtree maximum independent set, the answer is \ (\ max \ {f_ { 1,0}, f_ {1, 1}\}\)

\(f_{x,0}=\sum\limits_{y\in son_x}\{f_{y,0},f_{y,1}\}\)
\(f_{x,1}=\sum\limits_{y\in son_x}f_{y,0}+a_x\)

This is to consider all the circumstances of his son, then add weight does not consider his son (or real son) answers

\(g_{x,0}=\sum\limits_{y\in lson_x}\{f_{y,0},f_{y,1}\}\)
\(g_{x,1}=\sum\limits_{y\in lson_x}f_{y,0}+a_x\)

那么\(f_{x,0}=g_{x,0}+\max\{f_{hson_x,0},f_{hson_x,1}\}\)
\(f_{x,1}=g_{x,1}+f_{hson_x,0}\)

Define a matrix new operator \ (C = A * B \ ) represents \ (C_ {I, J} = \ max \ limits_k \ {A_ {I, K} + B_ {K, J} \} \) , is easy to prove that operation is associative but without having commutative

Transfer can be written as \ (\ begin {bmatrix} g_ {x, 0} & g_ {x, 0} \\ g_ {x, 1} & - \ infty \ end {bmatrix} * \ begin {bmatrix} f_ {y, 0 } \\ f_ {y, 1} \ end {bmatrix} = \ begin {bmatrix} f_ {x, 0} \\ f_ {x, 1} \ end {bmatrix} (y = hson_x) \)

Each heavy chain pair (actually measured and a bottom point where the intermediate portion of the heavy chain) to maintain the product attached to the matrix, in fact you may be noted that this result order is bottom-up, so the \ (DFN \) is under the subject line right after the tree is first left

Update heavy chain is jumping to the root, \ (O (1) \) to change the bottom \ (g \) value (as this will affect the side edges are light \ (g \) ), \ (O (\ log? ) \) modified heavy chain section connected product

A long time ago to write code

#include<cstdio>
#include<algorithm>
#include<string.h>
#define re register
#define ls(x) ((x)<<1)
#define rs(x) (((x)<<1)|1)
#define N 200005 
using namespace std;
struct Matrix{
    int num[2][2];
    inline Matrix(void){memset(num,0,sizeof num);}
    inline friend Matrix operator*(re Matrix a,re Matrix b){
        re int i,j,k;re Matrix c;
        for(i=0;i<2;++i)for(j=0;j<2;++j)for(k=0;k<2;++k)c.num[i][j]=max(c.num[i][j],a.num[i][k]+b.num[k][j]);
        return c;
    }
}ldpm[N<<1],t[N<<1];
int n,q,dp[N][2],size[N],son[N],pos[N],st[N],ed[N],antipos[N],h[N],cnt,scnt,ldp[N][2],top[N],val[N],dep[N],fa[N];
struct Edge{
    int to,next;
}e[N<<1];
inline void AddEdge(re int x,re int y){e[++cnt]=(Edge){y,h[x]};h[x]=cnt;}
inline void pushup(re int x){t[x]=t[ls(x)]*t[rs(x)];}
inline void dfs1(re int x,re int depth,re int prt){
//  printf("%d %d %d\n",x,depth,prt);
    re int i,y;dep[x]=depth;size[x]=1;
    dp[x][1]=val[x];fa[x]=prt;
    for(i=h[x];i;i=e[i].next){
        y=e[i].to;if(prt==y)continue;
        dfs1(y,depth+1,x);
        size[x]+=size[y];
        if(!son[x]||size[y]>size[son[x]])son[x]=y;
        dp[x][1]+=max(0,*dp[y]);
        *dp[x]+=max(0,max(*dp[y],dp[y][1]));
//      printf("%d->%d %d %d\n",x,y,dp[x][1],*dp[x]); 
    }
}
inline void dfs2(re int x,re int Top,re int prt){
    re int i,y;
    top[x]=Top;pos[x]=++scnt;antipos[scnt]=x;ldp[x][1]=val[x];st[x]=scnt;ed[Top]=scnt;
    if(son[x])dfs2(son[x],Top,x);
    for(i=h[x];i;i=e[i].next){
        y=e[i].to;if(y==prt||y==son[x])continue;
        dfs2(y,y,x);
        ldp[x][1]+=max(0,*dp[y]);*ldp[x]+=max(0,max(*dp[y],dp[y][1]));
    }
}
inline void Change(re int pos,re int l,re int r,re int k){
    if(l==r){t[pos]=ldpm[l];return;}
    re int mid=(l+r)>>1;
    if(k<=mid)Change(ls(pos),l,mid,k);
    else Change(rs(pos),mid+1,r,k);
    pushup(pos);
}
inline Matrix Query(re int pos,re int l,re int r,re int ql,re int qr){
    if(ql<=l&&r<=qr) return t[pos];
    int mid=(l+r)/2;
    if(qr<=mid)return Query(ls(pos),l,mid,ql,qr);
    if(ql>mid)return Query(rs(pos),mid+1,r,ql,qr);
    return Query(ls(pos),l,mid,ql,qr)*Query(rs(pos),mid+1,r,ql,qr);
}
inline Matrix Ask(re int x){return Query(1,1,scnt,st[top[x]],ed[top[x]]);}
inline void Build(re int pos,re int l,re int r){
    if(l>r)return ;
    if(l==r){t[pos]=ldpm[l];return;}//!
    re int mid=(l+r)>>1;
    Build(ls(pos),l,mid);Build(rs(pos),mid+1,r);
    pushup(pos);
}
inline void Change(re int x,re int y){
    re Matrix past,now;
    ldpm[st[x]].num[1][0]+=(y-val[x]);val[x]=y;
    while(x){
        past=Ask(top[x]);
        Change(1,1,scnt,st[x]);
        now=Ask(top[x]);
        x=fa[top[x]];
        ldpm[st[x]].num[0][0]+=max(now.num[0][0],now.num[1][0])-max(past.num[0][0],past.num[1][0]);
        ldpm[st[x]].num[0][1]=ldpm[st[x]].num[0][0];
        ldpm[st[x]].num[1][0]+=now.num[0][0]-past.num[0][0];
    }
}
inline void Read(void){
    re int i,j,x,y;
    scanf("%d%d",&n,&q);
    for(i=1;i<=n;++i)scanf("%d",val+i);
    for(i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        AddEdge(x,y);AddEdge(y,x);
    }
    dfs1(1,1,0);dfs2(1,1,0);
    for(i=1;i<=n;++i){
        ldpm[st[i]].num[0][0]=ldpm[st[i]].num[0][1]=ldp[i][0];
        ldpm[st[i]].num[1][0]=ldp[i][1];
//      cout<<'q'<<ldp[i][0]<<' '<<ldp[i][1]<<' '<<top[i]<<' '<<son[i]<<endl; 
    }
    Build(1,1,scnt);     
}
inline void Solve(void){
    re int x,y;re Matrix m;
    while(q--){
        scanf("%d%d",&x,&y);
        Change(x,y);
        m=Ask(1);
        printf("%d\n",max(m.num[0][0],m.num[1][0]));
    }
}
int main(void){
    Read();
    Solve();
    return 0;
}

Cute little people do not normally a problem this card \ (O (n \ log ^ 2n) \) garbage Algorithm

Global balanced binary tree

We really seems useless to consider the special nature of the heavy chain split, split looks long chain, real chains can be split

But a strange thing \ (LCT \) seems to be done \ (O (n \ log n ) \) only constant is too large

The problem is that \ (LCT \) can change the shape of the tree, and we do not need, we just need to do the chain tree split, high retention tree \ (O (\ log the n-) \) , can support a single point on the chain modify

Edible paper "QTREE solution of some of the research" available " globally balanced binary tree " approach

The method is simple, one for each of the heavy chain:

First, the heavy chain to pave a length \ (N \) sequence

\(s_i=size_i-size_{hson_i}\)

Determined minimum \ (I \) such \ (\ SUM \ limits_ {J =. 1} ^ I S_I \ geqslant \ FRAC {. 1} {2} \ SUM \ limits_ {J =. 1} ^ N S_I \) , and treated with the root of this point as a heavy chain, a heavy chain solid side even present, then virtual edge above the heavy chain

\ (EG \)
Enter a description of the picture here
(from \ (\ mathtt {\ color { red} Fee \ _cle6418} \) courseware)

For part of this contribution

inline int Build(re int l,re int r){
    if(l>r)return 0;
    re int pos=lower_bound(s+l,s+r+1,(s[r]-s[l-1]-1)/2+1+s[l-1])-s,ls,rs,x;
    x=st[pos],ls=Build(l,pos-1),rs=Build(pos+1,r);
    fa[*son[x]=ls]=fa[son[x][1]=rs]=x;pushup(x);
    return x;
}
inline int dfs(re int x){
    re int i,j,y,rt,top;
    for(i=x;i;i=bson[i])vis[i]=1;
    for(i=x;i;i=bson[i])
        for(j=h[i];j;j=e[j].next){
            if(vis[y=e[j].to])continue;
            fa[rt=dfs(y)]=i;
            a[i].a[1][1]+=max(b[rt].a[1][1],b[rt].a[2][1]);
            a[i].a[1][2]=a[i].a[1][1];
            a[i].a[2][1]+=b[rt].a[1][1]; 
        }
    for(top=0,i=x;i;i=bson[i])st[++top]=i,s[top]=s[top-1]+size[i]-size[bson[i]];
    return Build(1,top); 
}

All the words below

\(\mathtt{Code}\)

note

Although the matrix to facilitate transfer of promotion but in fact due to the matrix multiplication comes (C ^ 3 \) \ constant, not a lot of question cards in the past, some of the original \ (dp \) as the largest sub-segment and the range can be deleted heap Solution you can follow the tree, because the stack has mergability

example

dp dp sets

Outline

As the name suggests, it involves solving strange \ (dp \) process \ (dp \) issues common form of counting objects that satisfy certain \ (dp \) results

\ (EG \) seeking \ (LCS (A, B) = K \) and \ (B \) satisfies \ (P \) condition number scheme or not containing a given sub-string \ (N \) bit \ (K \ ) The number of decimal

It is easy to find these types of problems if the conversion is determined that the problem is really Platts \ (dp \)

The general solution idea is to solve the original judgment \ (dp \) counting process

Direct described explaining the nature of a more professional: inner layer \ (the DP \) as a result of the outer layer \ (the DP \) state will be \ (the DP \) method

References

Guess you like

Origin www.cnblogs.com/66t6/p/12381068.html
DP