P5024 defend the kingdom [multiplier + dp]

Of course, it will not nest ddp, write this question is of course consider optimizing bare dp matter, but it is very troublesome question, then, it becomes a black problem.

First of all, this is not the boss of the party model, with the right to seek maximum independent set of graph.

King does not consider constraints, there are
\ [dp [x] [0 ] + = dp [y] [1] \\ dp [x] [1] + = min (dp [y] [1], dp [y ] [0]) \]
now consider the restrictions, if each time constraints do dp, the complexity of the reach \ (O (the n-^ 2) \) , can not afford.

Obviously, for these restrictions, every change will not affect most other states.

For a constraint, we considered separately, first consider the case only to a limit of the city.

If the city is required military presence, then it would have been if we need troops in the best case, it has no effect; it would have been if the army does not need, at this time because the trees are all sub-optimal solution, then it only would be from it is the optimal solution to the root path of an impact .

If the city were asked not stationed, so similar to the above case, if it would have been stationed needs, then it will affect the path to the root node.

In summary, we can consider for each of the restrictions, only two points to some state path between the root to modify it? The answer is yes.

Node is assumed to be modified \ (X \) . First, this time in addition \ (sim root \ x \) state node on the path represented, other conditions are optimal. For updates on this path, and this path is actually doing a dp, and force \ (x \) is selected or not selected, thereby limiting the transfer.

Obviously this is feasible, but the complexity is still \ (O (the n-^ 2) \) , we need some means of optimization.

We update is easy to find a chain for a chain, we naturally think of using multiplication or tree section (they are maintained tree chain) to handle the transfer of each point.

To multiply, for example.

Consider first step of bare dp, one by one jump, each transfer from the son. Then we can jump paragraph by paragraph, each transfer from existing information in it? of course can.

First consider the case of only one point.

If we want to \ (x \) limit, then we might become like the whole map, convenient analysis

graph

Where the green part is \ (x \) optimal solution subtree.

Obviously we are after modifying one point, the impact on the optimal solution is certain , the new optimal solution produced is certain, which means we can pre-out by some means.

Consider a pretreatment by multiplying each point where the optimal fluctuates (option becomes not selected, not selected becomes selected) in this \ (x root \ \ sim) new optimal solution generated in the chain, i.e. a certain period of time after the jump a pretreatment to modify the segment dp optimal solution.

Then from \ (x \) tree multiplier jump \ (root \) , a new optimal solutions were combined and the answer is the limit under the conditions.

In fact, our pre-multiplication is based on a bare dp carried out. In other words, the information is used when multiplying the original point represents the optimal solution for each state, and then add a constraint, a do dp.

Image speaking, this pre-multiplication is set dp dp.

Then this multiplier how to do it?

Consider portray the state, apparently when the merger of several smaller sub-problems into larger sub-problems, these smaller sub-problems can not cross, otherwise it can not be divided based on the binary merge into larger sub-problems. Furthermore, the sub-questions must cover the entire state space. That is, when the state definition, we want to not leak.

That being the case, the first point, not difficult to think that we must not only record when multiplied \ (x \) state (0/1), but also to record it jumped \ (^ k \ 2) state steps ancestors.

For the second point, the range is not difficult to come up with a state included.

Set \ (f [0/1] [0/1 ] [k] [x] \) represents \ (X \) node becomes 0 is not available, when an optional, up \ (2 ^ k \) step ancestors \ (Y \) is an optional 0, 1 not optional , \ (Y \) is removed \ (X \) and \ (X \) a new optimal all other subtrees of the original optimal solution subtrees solution .

Below, it is assumed that the node 3 \ (X \) a \ (2 ^ k \) ancestors status is red portion

graph2

And 3 \ (2 ^ k \) ancestor (assumed to be \ (the root \) ) is represented by the state of the blue portion.

graph3


This can be a good merge state, statistical process after the answer, we just enumerate \ (x \) state and jump to multiply.

For nodes \ (Y \) , to its parent \ (X \) , there are
\ [f [1] [0 ] [0] [y] = dp [0] [x] -dp [1] [y ] \\ f [0] [1 ] [0] [y] = f [1] [1] [0] [y] = dp [1] [x] -min (dp [1] [y], dp [0] [y]) \ ]

Obtained transfer (CaO)
\ [F [0] [0] [J] [Y] = min (F [0] [0] [J-. 1] [Y] + F [0] [0] [J-. 1 ] [fa], f [0 ] [1] [j-1] [y] + f [1] [0] [j-1] [fa]) \\ f [0] [1] [j] [ y] = min (f [0 ] [0] [j-1] [y] + f [0] [1] [j-1] [fa], f [0] [1] [j-1] [ y] + f [1] [ 1] [j-1] [fa]) \\ f [1] [0] [j] [y] = min (f [1] [0] [j-1] [ y] + f [0] [ 0] [j-1] [fa], f [1] [1] [j-1] [y] + f [1] [0] [j-1] [fa] ) \\ f [1] [1 ] [j] [y] = min (f [1] [0] [j-1] [y] + f [0] [1] [j-1] [fa] , f [1] [1]
[j-1] [y] + f [1] [1] [j-1] [fa]) \] then the answer is to count, of course, is doubling statistical answer.

Starting from two different states to be modified to incorporate new point of doubling up the optimal solution, until the root node.

For two points to be modified \ (x, y \) situation, as we seek the same LCA, the first statistics \ (the X-\ the SIM LCA (the X-, the y-), the y-\ the SIM LCA (the X-, the y-) \) , then statistics \ (lca (x, y) \ sim root \) can be.

Attention to detail, when the \ (x, y \) two o'clock jump \ (lca \) son at the same time we need to subtract their two original optimal solution, and then further on to jump.

Complexity reduced to \ (O (nlogn) \) .

Tree cross-section is also a reason, the optimal solution after pretreatment changes.

Reference Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 100010
#define MOD 2520
#define E 1e-12
#define ll long long
using namespace std;
inline ll read()
{
    ll f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
struct rec{
    int next,ver;
}g[N<<1];
int head[N],tot,n,m;
ll dp[2][N],f[2][2][21][N],gi[21][N],t,dep[N],w[N];
inline void add(int x,int y)
{
    g[++tot].ver=y;
    g[tot].next=head[x],head[x]=tot;
}
inline void dfs(int x,int fa)
{
    dp[1][x]=w[x];dep[x]=dep[fa]+1;
    f[0][0][0][x]=INF,gi[0][x]=fa;
    for(int j=1;j<t;++j) gi[j][x]=gi[j-1][gi[j-1][x]];
    for(int i=head[x];i;i=g[i].next){
        int y=g[i].ver;
        if(y==fa) continue;
        dfs(y,x);
        dp[0][x]+=dp[1][y];
        dp[1][x]+=min(dp[1][y],dp[0][y]);
    } 
}
inline void init()
{
    queue<ll> q;
    q.push(1);
    f[1][0][0][1]=dp[0][0]-dp[1][1];
    f[0][1][0][1]=f[1][1][0][1]=dp[1][0]-min(dp[1][1],dp[0][1]);
    while(q.size()){
        ll x=q.front();q.pop();
        for(int i=head[x];i;i=g[i].next){
            int y=g[i].ver;
            if(y==gi[0][x]) continue;
            f[1][0][0][y]=dp[0][x]-dp[1][y];
            f[0][1][0][y]=f[1][1][0][y]=dp[1][x]-min(dp[1][y],dp[0][y]);
            for(int j=1;j<t;++j){
                int fa=gi[j-1][y];
                f[0][0][j][y]=min(f[0][0][j-1][y]+f[0][0][j-1][fa],f[0][1][j-1][y]+f[1][0][j-1][fa]);
                f[0][1][j][y]=min(f[0][0][j-1][y]+f[0][1][j-1][fa],f[0][1][j-1][y]+f[1][1][j-1][fa]);
                f[1][0][j][y]=min(f[1][0][j-1][y]+f[0][0][j-1][fa],f[1][1][j-1][y]+f[1][0][j-1][fa]);
                f[1][1][j][y]=min(f[1][0][j-1][y]+f[0][1][j-1][fa],f[1][1][j-1][y]+f[1][1][j-1][fa]);
            }
            q.push(y);
        }
    }
}
inline ll get(ll x,int a,ll y,int b)
{
    ll ans=0,lca;
    if(dep[x]<dep[y]) swap(x,y),swap(a,b);
    ll x0=INF,x1=INF,y0=INF,y1=INF,l0=INF,l1=INF;
    a?x1=dp[1][x]:x0=dp[0][x],b?y1=dp[1][y]:y0=dp[0][y];
    for(int j=t;j>=0;--j){
        ll t0=x0,t1=x1;
        if(dep[gi[j][x]]>=dep[y]){
            x0=min(t0+f[0][0][j][x],t1+f[1][0][j][x]);
            x1=min(t0+f[0][1][j][x],t1+f[1][1][j][x]);
            x=gi[j][x];
        }
    }
    if(x==y) lca=x,b?l1=x1:l0=x0;
    else {
        for(int j=t;j>=0;--j){
            if(gi[j][x]!=gi[j][y]){
                ll t0=x0,t1=x1,p0=y0,p1=y1;
                x0=min(t0+f[0][0][j][x],t1+f[1][0][j][x]);
                x1=min(t0+f[0][1][j][x],t1+f[1][1][j][x]);
                y0=min(p0+f[0][0][j][y],p1+f[1][0][j][y]);
                y1=min(p0+f[0][1][j][y],p1+f[1][1][j][y]);
                x=gi[j][x],y=gi[j][y];
            }
        }
        lca=gi[0][x];
        l0=dp[0][lca]-dp[1][x]-dp[1][y]+x1+y1;
        l1=dp[1][lca]-min(dp[0][x],dp[1][x])-min(dp[0][y],dp[1][y])+min(x1,x0)+min(y1,y0);
    }
    if(lca==1) ans=min(l0,l1);
    else{
        for(int j=t;j>=0;--j){
            if(dep[gi[j][lca]]>1){
                ll t0=l0,t1=l1;
                l0=min(t0+f[0][0][j][lca],t1+f[1][0][j][lca]);
                l1=min(t0+f[0][1][j][lca],t1+f[1][1][j][lca]);
                lca=gi[j][lca];
            }
        }
        ans=min(dp[0][1]-dp[1][lca]+l1,dp[1][1]-min(dp[0][lca],dp[1][lca])+min(l1,l0));
    }
    return ans<INF?ans:-1;
}
int main()
{
    n=read(),m=read();
    char op[5];
    cin>>op;
    t=log2(n)+1;
    for(int i=1;i<=n;++i) w[i]=read();
    for(int i=1;i<n;++i){
        ll u=read(),v=read();
        add(u,v),add(v,u);
    }
    dfs(1,0);
    init();
    while(m--){
        ll x=read(),a=read(),y=read(),b=read();
        if(a==0&&b==0&&(gi[0][x]==y||gi[0][y]==x)){
            puts("-1");continue;
        }
        printf("%lld\n",get(x,a,y,b));
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/DarkValkyrie/p/11770516.html