• luogu5024 [NOIp2018]保卫王国 (动态dp)


    可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵

      1 #include<bits/stdc++.h>
      2 #define CLR(a,x) memset(a,x,sizeof(a))
      3 using namespace std;
      4 typedef long long ll;
      5 typedef pair<int,int> pa;
      6 const int maxn=1e5+10;
      7 const ll inf=1e17;
      8 
      9 inline ll rd(){
     10     ll x=0;char c=getchar();int neg=1;
     11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     13     return x*neg;
     14 }
     15 
     16 int N,M,p[maxn];
     17 int eg[maxn*2][2],egh[maxn],ect,fa[maxn][22],dep[maxn];
     18 ll f[maxn][2];
     19 struct Mat{
     20     int n,m;ll a[3][3];
     21     Mat(int a0=0,int a1=0,ll a2=0,ll a3=0,ll a4=0,ll a5=0){
     22         n=a0,m=a1;a[1][1]=a2,a[1][2]=a3,a[2][1]=a4,a[2][2]=a5;
     23     }
     24 }trans[maxn][22];
     25 
     26 inline Mat operator * (Mat a,Mat b){
     27     Mat re;
     28     re.n=a.n,re.m=b.m;
     29     for(int i=1;i<=re.n;i++){
     30         for(int j=1;j<=re.m;j++){
     31             re.a[i][j]=inf;
     32             for(int k=1;k<=a.m;k++){
     33                 re.a[i][j]=min(re.a[i][j],a.a[i][k]+b.a[k][j]);
     34             }
     35         }
     36     }return re;
     37 }
     38 
     39 inline void adeg(int a,int b){
     40     eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect;
     41 }
     42 
     43 void dfs1(int x){
     44     f[x][0]=0,f[x][1]=p[x];
     45     for(int i=egh[x];i;i=eg[i][1]){
     46         int b=eg[i][0];if(b==fa[x][0]) continue;
     47         fa[b][0]=x,dep[b]=dep[x]+1;
     48         dfs1(b);
     49         f[x][0]+=f[b][1],f[x][1]+=min(f[b][0],f[b][1]);
     50     }
     51 }
     52 
     53 void dfs2(int x){
     54     if(fa[x][0]){
     55         ll s0,s1;
     56         s0=f[fa[x][0]][0]-f[x][1];
     57         s1=f[fa[x][0]][1]-min(f[x][0],f[x][1]);
     58         trans[x][0]=Mat(2,2,inf,s1,s0,s1);
     59         for(int i=0;fa[x][i]&&fa[fa[x][i]][i];i++){
     60             fa[x][i+1]=fa[fa[x][i]][i];
     61             trans[x][i+1]=trans[x][i]*trans[fa[x][i]][i];
     62         }
     63     }
     64     for(int i=egh[x];i;i=eg[i][1]){
     65         int b=eg[i][0];if(b==fa[x][0]) continue;
     66         dfs2(b);
     67     }
     68 }
     69 
     70 inline ll update(int x,int y,Mat &fx,Mat &fy){
     71     for(int i=log2(dep[x]-dep[y]);i>=0&&dep[x]!=dep[y];i--){
     72         if(dep[fa[x][i]]>=dep[y])
     73             fx=fx*trans[x][i],x=fa[x][i];
     74     }
     75     int lca;Mat fl;
     76     if(x==y){
     77         lca=y;fl=fx;
     78         if(fy.a[1][1]==inf) fl.a[1][1]=inf;
     79         else if(fy.a[1][2]==inf) fl.a[1][2]=inf;
     80     }else{
     81         for(int i=log2(dep[x]);i>=0;i--){
     82             if(fa[x][i]!=fa[y][i]){
     83                 fx=fx*trans[x][i],fy=fy*trans[y][i];
     84                 x=fa[x][i],y=fa[y][i];
     85             }
     86         }
     87         lca=fa[x][0];
     88         // printf("~%d %d %d %d %d %d
    ",x,fx.a[1][1],fx.a[1][2],y,fy.a[1][1],fy.a[1][2]);
     89         ll a0=f[lca][0]-f[x][1]-f[y][1]+fx.a[1][2]+fy.a[1][2];
     90         ll a1=f[lca][1]-min(f[x][1],f[x][0])-min(f[y][1],f[y][0])+min(fx.a[1][1],fx.a[1][2])+min(fy.a[1][1],fy.a[1][2]);
     91         fl=Mat(1,2,a0,a1,0,0);
     92     }
     93     for(int i=log2(dep[lca]);i>=0;i--){
     94         if(fa[lca][i]){
     95             fl=fl*trans[lca][i];
     96             lca=fa[lca][i];
     97         }
     98     }
     99     return min(fl.a[1][1],fl.a[1][2]);
    100 }
    101 
    102 int main(){
    103     // freopen("testdata.in","r",stdin);
    104     int i,j,k;
    105     N=rd(),M=rd();rd();
    106     for(i=1;i<=N;i++) p[i]=rd();
    107     for(i=1;i<N;i++){
    108         int a=rd(),b=rd();
    109         adeg(a,b);adeg(b,a);
    110     }
    111     dep[1]=1;dfs1(1);dfs2(1);
    112     for(i=1;i<=M;i++){
    113         int a=rd(),x=rd(),b=rd(),y=rd();
    114         if(dep[a]<dep[b]) swap(a,b),swap(x,y);
    115         if(fa[a][0]==b&&!x&&!y){
    116             printf("-1
    ");continue;
    117         }
    118         Mat fx,fy;
    119         if(x) fx=Mat(1,2,inf,f[a][1],0,0);
    120         else fx=Mat(1,2,f[a][0],inf,0,0);
    121         if(y) fy=Mat(1,2,inf,f[b][1],0,0);
    122         else fy=Mat(1,2,f[b][0],inf,0,0);
    123         printf("%lld
    ",update(a,b,fx,fy));
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    powermock测试
    一些疑惑
    Java基础总结3
    Java学习路线
    Java基础总结2
    关于我
    翻转单词序列
    和为s的两个数字
    和为s的连续正数序列
    数组中只出现一次的数字
  • 原文地址:https://www.cnblogs.com/Ressed/p/9967256.html
Copyright © 2020-2023  润新知