zoukankan      html  css  js  c++  java
  • 【NOIP2018】保卫王国 动态dp

    此题场上打了一个正确的$44pts$,接着看错题疯狂$rush$“正确”的$44pts$,后来没$rush$完没将之前的代码$copy$回去,直接变零分了。。。。。

    这一题我们显然有一种$O(nm)$的做法

    令$f[u][0]$表示在以$u$为根的子树内部署军队,且$u$不部署军队的最小代价。

    令$f[u][1]$表示在以$u$为根的子树内部署军队,且$u$部署军队的最小代价。

    结合题意(重要!)不难推出:

    $f[u][0]=sum_{v∈son[u]} f[v][1]$

    $f[u][1]=val_u+sum_{v∈son[u]} min(f[v][0],f[v][1])}$

    考虑满足能选/不能选的要求,我们只需要临时将被选择点的权值赋值为$INF$或$-INF$即可。

    考虑这棵树是一条链的情况:我们用一棵线段树,每个节点维护一个答案矩阵(该区间左端点驻军/可能不驻军,该区间右端点驻军/可能不驻军时的最小代价)。我们求一个节点的答案矩阵,显然可以通过其儿子的答案矩阵,通过大力分类讨论(详见代码)实现更新。

    当出现修改权值的情况时,大力改一改然后$pushup$即可。

    我们考虑将这一个链上做法扩展到树上。我们用树链剖分将整棵树剖成若干条链,对于轻边上的一对节点$(u,son[u])$,我们将$son[u]$所在链的信息加入节点$u$所对应答案矩阵内即可(详见代码)。

    一遍过样例开了$O2$就过了美滋滋

      1 #include<bits/stdc++.h>
      2 #define mid ((a[x].l+a[x].r)>>1)
      3 #define L long long 
      4 #define INF (1LL<<50)
      5 #define LOW (1LL<<40)
      6 #define M 100005
      7 using namespace std;
      8 
      9 struct edge{int u,next;}e[M*2]={0}; int head[M]={0},use=0;
     10 void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;}
     11 
     12 int siz[M]={0},dfn[M]={0},rec[M]={0},top[M]={0},dn[M]={0},son[M]={0},fa[M]={0},t=0;
     13 
     14 void dfs(int x){
     15     siz[x]=1;
     16     for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]){
     17         fa[e[i].u]=x;
     18         dfs(e[i].u);
     19         siz[x]+=siz[e[i].u];
     20         if(siz[son[x]]<siz[e[i].u]) son[x]=e[i].u;
     21     }
     22 }
     23 void dfs(int x,int Top){
     24     top[x]=Top; dfn[x]=++t; rec[t]=x;
     25     if(son[x]) dfs(son[x],Top),dn[x]=dn[son[x]]; else dn[x]=x;
     26     for(int i=head[x];i;i=e[i].next) 
     27     if(e[i].u!=fa[x]&&e[i].u!=son[x]) dfs(e[i].u,e[i].u);
     28 }
     29 
     30 L f[M][2]={0},val[M]={0};
     31 void dp(int x){
     32     f[x][1]=val[x];
     33     for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]){
     34         dp(e[i].u);
     35         f[x][0]+=f[e[i].u][1];
     36         f[x][1]+=min(f[e[i].u][0],f[e[i].u][1]);
     37     }
     38 }
     39 
     40 struct mat{
     41     L a[2][2]; mat(){memset(a,0,sizeof(a));}
     42     mat(L x){a[0][0]=a[0][1]=a[1][0]=a[1][1]=x;}
     43     mat(L a1,L a2,L a3,L a4){a[0][0]=a1; a[0][1]=a2; a[1][0]=a3; a[1][1]=a4;}
     44     L ans(){ return min(min(a[0][0],a[0][1]),min(a[1][0],a[1][1]));}
     45     void upd(L now){a[0][0]+=now; a[0][1]+=now; a[1][0]+=now;}
     46     friend mat operator *(mat a,mat b){
     47         mat c=INF;
     48         for(int i=0;i<2;i++)
     49         for(int j=0;j<2;j++){
     50             for(int i1=0;i1<2;i1++)
     51             for(int j1=0;j1<2;j1++)
     52             if(!(i1==1&&j1==1))
     53             c.a[i][j]=min(c.a[i][j],a.a[i][i1]+b.a[j1][j]);
     54         }
     55         return c;
     56     }
     57 }wei[M];
     58 struct seg{int l,r; mat s;}a[M<<2];
     59 void pushup(int x){a[x].s=a[x<<1].s*a[x<<1|1].s;}
     60 
     61 void build(int x,int l,int r){
     62     a[x].l=l; a[x].r=r;
     63     if(l==r){
     64         int u=rec[l]; L g0=0,g1=val[u];
     65         for(int i=head[u];i;i=e[i].next)
     66         if(e[i].u!=fa[u]&&e[i].u!=son[u]){
     67             g0+=f[e[i].u][1];
     68             g1+=min(f[e[i].u][0],f[e[i].u][1]);
     69         }
     70         a[x].s=wei[l]=mat(g1,g1,g1,g0);
     71         return;
     72     }
     73     build(x<<1,l,mid); build(x<<1|1,mid+1,r);
     74     pushup(x);
     75 }
     76 mat query(int x,int l,int r){
     77     if(l<=a[x].l&&a[x].r<=r) return a[x].s;
     78     if(r<=mid) return query(x<<1,l,r);
     79     if(mid<l) return query(x<<1|1,l,r);
     80     return query(x<<1,l,r)*query(x<<1|1,l,r);
     81 }
     82 mat query(int x){return query(1,dfn[top[x]],dfn[dn[x]]);}
     83 L solve(){mat hh=query(1); return hh.ans();} 
     84 
     85 void updata(int x,int k){
     86     if(a[x].l==a[x].r) return void(a[x].s=wei[k]);
     87     if(k<=mid) updata(x<<1,k); else updata(x<<1|1,k);
     88     pushup(x);
     89 }
     90 void Updata(int x,L Val){
     91     L chg=Val-val[x]; val[x]+=chg;
     92     wei[dfn[x]].upd(chg);
     93     while(x){
     94         mat last=query(x);
     95         L lg1=last.ans(),lg0=min(last.a[0][0],last.a[0][1]);
     96         
     97         updata(1,dfn[x]);
     98         
     99         mat now=query(x);
    100         L ng1=now.ans(),ng0=min(now.a[0][0],now.a[0][1]); 
    101         
    102         x=fa[top[x]]; if(!x) return;
    103         wei[dfn[x]].upd(ng1-lg1);
    104         wei[dfn[x]].a[1][1]+=ng0-lg0;
    105     }
    106 }
    107 
    108 
    109 int n,m; char op[10];
    110 
    111 int main(){
    112     //freopen("defense.in","r",stdin);
    113     //freopen("defense.out","w",stdout);
    114     scanf("%d%d%s",&n,&m,op);
    115     for(int i=1;i<=n;i++) scanf("%lld",val+i);
    116     for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    117     dfs(1);
    118     dfs(1,1);
    119     dp(1);
    120     build(1,1,n);
    121     //cout<<solve()<<endl;
    122     while(m--){
    123         int A,x,B,y; scanf("%d%d%d%d",&A,&x,&B,&y);
    124         L lastA=val[A],lastB=val[B],chg=0;
    125         
    126         if(x==0) Updata(A,INF);
    127         else Updata(A,-INF);
    128         
    129         if(y==0) Updata(B,INF);
    130         else Updata(B,-INF);
    131         
    132         L res=solve();
    133         if(x) res+=INF+lastA;
    134         if(y) res+=INF+lastB;
    135         
    136         Updata(A,lastA);
    137         Updata(B,lastB);
    138         
    139         if(res>LOW){printf("-1
    "); continue;}
    140         printf("%lld
    ",res);
    141     }
    142 }
  • 相关阅读:
    2019暑假中山纪中集训游记
    pytest入门学习(1)
    学习makefile与autoconfig笔记,持续更新
    新手安装 hadoop、hive和hbase 笔记
    新装ubuntu 12.04 , 使用技巧
    JDK1.7 和 jetty配置教程
    python成长之路一
    IDM下载神器
    测试
    Hadoop命令
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10325025.html
Copyright © 2011-2022 走看看