"NOIP 2019Day2 T3" to defend the kingdom (defense)

Review questions NOIP2018 found just think about it or be able to come up with some things.

For example, this question is a template DDP questions, he just made the subject of doubling optimized DP.

For tree $ n $ nodes given every point a little right $ v_i $, a total of $ Q $ times inquiry.

Each interrogation specify two points taken or not taken status, query tree cover set minimum weight.

If the minimum weight set does not exist coverage, output $ $ -1

For $ 100 \% guaranteed $ $ 1 \ leq n, m \ leq 10 ^ 5, 1 \ leq v_i \ leq 10 ^ 9 $

Solution :

  We set $ g [u] [0/1] $ indicate whether the selected node $ u $, $ u $ subtree covering minimum weight set.

  One obvious metastasis $ g [u] [0] = \ sum \ limits_ {v \ in u_ {son}} g [v] [1], g [u] [1] = val [u] + \ sum \ limits_ {v \ in u_ {son}} min (g [v] [0], g [v] [1]) $

  In order to address a $ Q $ inquiry, we need to set the multiplier array to optimize the shift.

Wherein provided $ f [u] [i] [p] [q] (wherein p, q = 0,1) $ represents from $ father (u) $ jump up to $ U $ $ I $ 2 ^ node step, wherein U $ $ state $ p $, $ u $ $ 2 ^ jump up state node I $ $ Q $ is obtained this minimum contribution.

We will be apparent by one $ dfs $, calculated $ f [u] [0] [0/1] [0/1], g [u] [0/1] $ value

  •  $ F [u] [0] [0] [0] = inf $
  •  $f[u][0][0][1] = val[father(u)] + \sum\limits_{v \in father(u)_{son} v \neq u}min\{g[v][0],g[v][1]\}$
  •  $f[u][0][1][0] =\sum\limits_{v \in father(u)_{son}} g[v][1]$
  •  $f[u][0][1][1]= val[father(u)] + \sum\limits_{v \in father(u)_{son} v \neq u}min\{g[v][0],g[v][1]\}$

Then we can also array $ O (n \ log_2 \ n) $ complexity of multiplication of the above-described pretreatment, $ LCA $ array and

When dealing with each inquiry, to $ u, v $ in the same chain of circumstances and $ u, v $ circumstances that are not on a chain to discuss

(Mainly upward jump of position and calculate different contribution)

$ Ret0 two variables recorded at the time of jump up, ret1 $ represents the current node taking or not taking the current subtree cover set minimum weight.

Since doubling the number of steps upward jump pretreatment is completed, it will only ask once jump up $ log_2n $ step,

Therefore, the time complexity of this problem is $ O ((n + m) log_2 n) $

# include <bits/stdc++.h>
# define int long long
# define inf (1e12)
using namespace std;
const int N=5e5+10;
struct rec{ int pre,to;}a[N<<1];
int n,m,tot; char type[10];
int f[N][22][2][2],g[N][2],d[N][22],dep[N];
int sum1[N],sum2[N],head[N],val[N];
inline int read()
{
    int X=0,w=0; char c=0;
    while(c<'0'||c>'9') {w|=c=='-';c=getchar();}
    while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
    return w?-X:X;
}
void write(int x) {
    if (x<0) putchar('-'),x=-x;
    if (x>9) write(x/10);
    putchar('0'+x%10);
}
void adde(int u,int v) {
    a[++tot].pre=head[u];
    a[tot].to=v;
    head[u]=tot;
}
void dfs1(int u,int fa) {
    dep[u]=dep[fa]+1;
    g[u][0]=0; g[u][1]=val[u]; d[u][0]=fa;
    sum1[u]=0; sum2[u]=0;
    for (int i=head[u];i;i=a[i].pre) {
        int v=a[i].to; if (v==fa) continue;
        dfs1(v,u);
        g[u][0]+=g[v][1];
        g[u][1]+=min(g[v][0],g[v][1]);
        sum1[u]+=g[v][1];
        sum2[u]+=min(g[v][0],g[v][1]);
    }
}
void dfs2(int u,int fa) {
    for (int i=head[u];i;i=a[i].pre) {
        int v=a[i].to; if (v==fa) continue;
        dfs2(v,u);
    }
    if (u != 1) {
        f[u][0][0][0] = inf;
        f[u][0][0][1] = val[fa] + sum2[fa] - min(g[u][0],g[u][1]);
        f[u][0][1][0] = sum1[fa] - g[u][1];
        f[u][0][1][1] = val[fa] + sum2[fa] - min(g[u][0],g[u][1]);
    }
}
int lca(int u,int v) {
    if (dep[u]<dep[v]) swap(u,v);
    for (int i=21;i>=0;i--)
     if (dep[d[u][i]]>=dep[v]) u=d[u][i];
    if (u==v) return u;
    for (int i=21;i>=0;i--)
     if (d[u][i]!=d[v][i]) u=d[u][i],v=d[v][i];
    return d[u][0];
}
int work2(int u,int op1,int v,int op2) {
    int ret0=g[u][0],ret1=g[u][1];
    if (op1 == 1) ret0=inf; else ret1=inf;
    bool flag = true;
    int tmp0,tmp1;
    for (int i=21;i>=0;i--) {
        if (dep[d[u][i]]<=dep[v]) continue;
        tmp0=ret0,tmp1=ret1;
        ret0 = min(tmp0+f[u][i][0][0],tmp1+f[u][i][1][0]);
        ret1 = min(tmp0+f[u][i][0][1],tmp1+f[u][i][1][1]);
        u = d[u][i];
    }
    
    tmp0=ret0,tmp1=ret1;
    ret0 = tmp1 + sum1[v] - g[u][1];
    ret1 = min(tmp1,tmp0) + sum2[v] - min(g[u][0],g[u][1]) + val[v];
    if (op2 == 0) ret1=inf; else ret0=inf;
    u = v;
    for (int i=21;i>=0;i--) {
        if (dep[d[u][i]]<dep[1]) continue;
        tmp0=ret0,tmp1=ret1;
        ret0 = min(tmp0+f[u][i][0][0],tmp1+f[u][i][1][0]);
        ret1 = min(tmp0+f[u][i][0][1],tmp1+f[u][i][1][1]);
        u=d[u][i];
    }
    int ans = min(ret0,ret1);
    if (ans>=inf) return -1; else return ans;
}
int work(int u,int op1,int v,int op2) {
    if (dep[u]<dep[v]) swap(u,v),swap(op1,op2);
    int l=lca(u,v);
    if (l == v) return work2(u,op1,v,op2);
    int ret0=g[u][0],ret1=g[u][1];
    if (op1 == 1) ret0=inf; else ret1=inf;
    bool flag = true; int tmp0,tmp1;
    for (int i=21;i>=0;i--) {
        if (dep[d[u][i]]<=dep[l]) continue;
        tmp0=ret0,tmp1=ret1;
        ret0 = min(tmp0+f[u][i][0][0],tmp1+f[u][i][1][0]);
        ret1 = min(tmp0+f[u][i][0][1],tmp1+f[u][i][1][1]);
        u = d[u][i];
    }
    int val1[2]; val1[0] = ret0; val1[1] = ret1;
    ret0=g[v][0],ret1=g[v][1];
    if (op2 == 1) ret0=inf; else ret1=inf;
    flag = true; 
    for (int i=21;i>=0;i--) {
        if (dep[d[v][i]]<=dep[l]) continue;
        tmp0=ret0,tmp1=ret1;
        ret0 = min(tmp0+f[v][i][0][0],tmp1+f[v][i][1][0]);
        ret1 = min(tmp0+f[v][i][0][1],tmp1+f[v][i][1][1]);
        v =d [v] [i]; 
    } 
    Int Val 2 [ 2 ]; Val 2 [ 0 ] = ret0; Val 2 [ 1 ] = ret1; 
    ret0 = VAL1 [ 1 ] + Val 2 [ 1 ] + sum1 [l] g [i] [ 1 ] -g [s] [ 1 ]; 
    ret1 = val [l] + min (VAL1 [ 0 ], VAL1 [ 1 ]) + min (Val 2 [ 0 ], Val 2 [ 1 ]) + SUM2 [l] - min (G [i] [ 0 ], G [ u] [ 1 ]) - min (g [i] [ 0 ], g [i] [ 1 ]); 
    u = l;
    for ( int i =21;i>=0;i--) {
        if (dep[d[u][i]]<dep[1]) continue;
        tmp0=ret0,tmp1=ret1;
        ret0 = min(tmp0+f[u][i][0][0],tmp1+f[u][i][1][0]);
        ret1 = min(tmp0+f[u][i][0][1],tmp1+f[u][i][1][1]);
        u=d[u][i];
    }
    
    int ans = min(ret0,ret1);
    if (ans>=inf) return -1; else return ans;
}
signed main()
{
    n=read();m=read(); scanf("%s",type);
    for (int i=1;i<=n;i++) val[i]=read();
    for (int i=2;i<=n;i++) {
        int u=read(),v=read();
        adde(u,v); adde(v,u);
    }
    dfs1(1,0); dfs2(1,0);
    for (int i=1;i<=21;i++)
     for (int j=1;j<=n;j++)
      d[j][i]=d[d[j][i-1]][i-1];
    for (int i=1;i<=21;i++)
     for (int u=1;u<=n;u++) {
         f[u][i][0][0]=f[u][i][0][1]=f[u][i][1][0]=f[u][i][1][1]=inf;
         for (int p=0;p<=1;p++) {
              f[u][i][0][0] = min(f[u][i][0][0],f[u][i-1][0][p] + f[d[u][i-1]][i-1][p][0]);
            f[u][i][0][1] = min(f[u][i][0][1],f[u][i-1][0][p] + f[d[u][i-1]][i-1][p][1]);
            f[u][i][1][0] = min(f[u][i][1][0],f[u][i-1][1][p] + f[d[u][i-1]][i-1][p][0]);
            f[u][i][1][1] = min(f[u][i][1][1],f[u][i-1][1][p] + f[d[u][i-1]][i-1][p][1]);
          }
    }
    while (m--) {
        int u=read(),op1=read(),v=read(),op2=read(); 
        int ans = work(u,op1,v,op2);
        write(ans); putchar('\n');
    }
    return 0;
}
defense

 

Guess you like

Origin www.cnblogs.com/ljc20020730/p/11614382.html