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 }
  • 相关阅读:
    array and ram
    char as int
    pointer of 2d array and address
    Install SAP HANA EXPRESS on Google Cloud Platform
    Ubuntu remount hard drive
    Compile OpenSSL with Visual Studio 2019
    Install Jupyter notebook and tensorflow on Ubuntu 18.04
    Build OpenCV text(OCR) module on windows with Visual Studio 2019
    Reinstall VirtualBox 6.0 on Ubuntu 18.04
    Pitfall in std::vector<cv::Mat>
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10325025.html
Copyright © 2011-2022 走看看