暴力dp非常显然,设f[i][0/1]表示i号点不选/选时i子树内的答案,则f[i][0]=Σf[son][1],f[i][1]=a[i]+Σmin(f[son][0],f[son][1])。

  注意到B的部分分,可以想到每次修改只会对修改点到根的路径上的点的dp值产生影响。

  考虑如何优化修改路径这一过程,先看只修改一个点的情况。

  由于每次修改并非累积,事实上应该考虑一种预处理来快速得到答案,并且发现其实最终我们只需要f[root][]。容易想到倍增。设f[x][k][0/1][0/1]表示x号点为0/1时其2k级祖先为0/1时这条链上的答案,即其2k级祖先的子树-x的子树的答案。这个东西本身就是可减的,即知道了在x号点子树内的y点选/不选的情况下x子树的答案、y号点选/不选的情况下y子树的答案,将其相减就是x子树去掉y子树的答案。

  倍增数组并不难求,显然我们已经有f[x][0][][],在2k-1级祖先那里合并得到2k级的答案,考虑2k-1级祖先选还是不选取个min即可,大约就是floyd/矩乘。回答询问同样也是类似的很正常的倍增。那么只改一个点就能做了。

  再考虑改两个点,其实基本类似。两个点倍增求出到他们的lca下方一个点的答案,以此更新lca答案,再从lca倍增跳到根即可。对其中一点是另一点祖先的情况最好特判。听起来不是很复杂但写起来得考虑清楚。

  另一种做法是ddp,暂时觉得不太学的动,好像也很久没学新姿势了。感觉倍增做法看上去还是比较noip的,虽然考场上被神仙t2和完全没碰过但知道能做这个题的ddp冲昏头脑肯定想不出来。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 100000000000ll
#define N 100010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{int x=0,f=1;char c=getchar();while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();return x*f;
}
int n,m,a[N],p[N],fa[N][18],deep[N],t;
ll f[N][2],g[N][18][2][2];
struct data{int to,nxt,len;
}edge[N<<1];
struct data2{ll x,y;int id;};
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k)
{f[k][0]=0,f[k][1]=a[k];for (int i=p[k];i;i=edge[i].nxt)if (edge[i].to!=fa[k][0]){deep[edge[i].to]=deep[k]+1;fa[edge[i].to][0]=k;dfs(edge[i].to);f[k][0]+=f[edge[i].to][1];f[k][1]+=min(f[edge[i].to][0],f[edge[i].to][1]);}for (int i=p[k];i;i=edge[i].nxt)if (edge[i].to!=fa[k][0]){g[edge[i].to][0][0][0]=inf;g[edge[i].to][0][0][1]=f[k][1]-min(f[edge[i].to][0],f[edge[i].to][1]);g[edge[i].to][0][1][0]=f[k][0]-f[edge[i].to][1];g[edge[i].to][0][1][1]=f[k][1]-min(f[edge[i].to][0],f[edge[i].to][1]);}
}
void pre()
{for (int j=1;j<18;j++){for (int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];for (int i=1;i<=n;i++)for (int x=0;x<2;x++)for (int y=0;y<2;y++)g[i][j][x][y]=min(g[i][j-1][x][0]+g[fa[i][j-1]][j-1][0][y],g[i][j-1][x][1]+g[fa[i][j-1]][j-1][1][y]);}
}
int lca(int x,int y)
{if (deep[x]<deep[y]) swap(x,y);for (int j=17;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];if (x==y) return x;for (int j=17;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];return fa[x][0];
}
data2 query(int x,int root,int isup,ll tx,ll ty)
{data2 u;u.x=tx,u.y=ty;for (int j=17;~j;j--)if (deep[fa[x][j]]>deep[root]){tx=u.x,ty=u.y;u.x=min(tx+g[x][j][0][0],ty+g[x][j][1][0]);u.y=min(tx+g[x][j][0][1],ty+g[x][j][1][1]);x=fa[x][j];}u.id=x;if (isup){tx=u.x,ty=u.y;u.x=min(tx+g[x][0][0][0],ty+g[x][0][1][0]);u.y=min(tx+g[x][0][0][1],ty+g[x][0][1][1]);}return u;
}
int main()
{
#ifndef ONLINE_JUDGEfreopen("bzoj5466.in","r",stdin);freopen("bzoj5466.out","w",stdout);const char LL[]="%I64d\n";
#elseconst char LL[]="%lld\n";
#endifn=read(),m=read();read();for (int i=1;i<=n;i++) a[i]=read();for (int i=1;i<n;i++){int x=read(),y=read();addedge(x,y),addedge(y,x);}fa[1][0]=1;dfs(1);pre();while (m--){int x=read(),opx=read(),y=read(),opy=read();if (deep[x]<deep[y]) swap(x,y),swap(opx,opy);if (opx==0&&opy==0&&fa[x][0]==y) {printf("-1\n");continue;}int k=lca(x,y);if (k==y){data2 u=query(x,k,0,opx==0?f[x][0]:inf,opx==1?f[x][1]:inf);ll tx=u.x,ty=u.y;u.x=f[k][0]+ty-f[u.id][1];u.y=f[k][1]+min(tx,ty)-min(f[u.id][0],f[u.id][1]);if (opy==0) u.y=inf;else u.x=inf;if (k!=1) u=query(k,1,1,u.x,u.y);printf(LL,min(u.x,u.y));}else{data2 u=query(x,k,0,opx==0?f[x][0]:inf,opx==1?f[x][1]:inf);data2 v=query(y,k,0,opy==0?f[y][0]:inf,opy==1?f[y][1]:inf);data2 w;w.x=f[k][0]+u.y-f[u.id][1]+v.y-f[v.id][1];w.y=f[k][1]+min(u.x,u.y)-min(f[u.id][0],f[u.id][1])+min(v.x,v.y)-min(f[v.id][0],f[v.id][1]);w=query(k,1,1,w.x,w.y);printf(LL,min(w.x,w.y));}}return 0;
}

转载于:https://www.cnblogs.com/Gloid/p/10022777.html

BZOJ5466 NOIP2018保卫王国(倍增+树形dp)相关推荐

  1. 吉吉王国(二分+树形dp)

    吉吉王国 题意: n个点,m个边,有边权,现在要求叶子节点无法与1号点连通,要求切断的总长度不能超过m,且切断的最长的长度尽可能断 题解: 题意的前半部分可以确定是树形dp,后半部分可以确定为是二分 ...

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

    可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵 1 #include<bits/stdc++.h> 2 #define CLR(a,x) mems ...

  3. jzoj5248-[NOIP2017提高A组模拟8.10]花花的聚会【倍增,树形dp】

    正题 题目链接:https://gmoj.net/senior/#main/show/5248 题目大意 nnn个点的一棵树,有mmm张票(v,k,w)(v,k,w)(v,k,w)表示可以在点vvv买 ...

  4. 线性代数四之动态DP(广义矩阵加速)——Can you answer these queries III,保卫王国

    动态DP--广义矩阵加速 SP1716 GSS3 - Can you answer these queries III description solution code [NOIP2018 提高组] ...

  5. 【bzoj2500】幸福的道路 树形dp+倍增RMQ+二分

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825389.html 题目描述 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一 ...

  6. 【树形dp】vijos1144小胖守皇宫

    细节很精妙 描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状:某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步 ...

  7. Uoj 441 保卫王国

    Uoj 441 保卫王国 动态 \(dp\) .今天才来写这个题. 设 \(f[u][0/1]\) 表示子树 \(u\) 中不选/选 \(u\) 时的最小权值和,显然有:\(f[u][0]=\sum ...

  8. AcWing1077. 皇宫看守(树形DP)题解

    题目传送门 题目描述 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见. 大内保卫森严,三步一岗,五步一哨,每个宫殿 ...

  9. bzoj 3611: [Heoi2014]大工程(虚树+树形DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MB Submit: 1697  Solved: 718 [Submit][Stat ...

最新文章

  1. 第六届全国大学生智能汽车竞赛获奖名单
  2. iOS 最新发布App Store流程
  3. 实现数组类(C++ 拷贝构造函数、拷贝函数)要判断赋值左右对象不相等,坑惨了...
  4. python 提示错误AttributeError: type object 'str' has no attribute '_name_'
  5. 7-72 分解质因数 (20 分)
  6. python基本程序结构有几种_python基础梳理(一)(推荐)
  7. 实体安全主要指计算机及网络硬件设备,计算机安全中的实体安全主要是指什么?...
  8. [费用流专题]Going Home,Minimum Cost,工作安排
  9. 卡农 matlab,matlab 编的卡农
  10. Hadoop DataNode : Address already in use
  11. 深入理解docker graph driver - DeviceMapper
  12. 查找字符串中元素出现的次数
  13. 计算机控制技术数据存储器有,计算机控制技术复习资料.doc
  14. html5 前端js框架,前端h5框架总结
  15. xmlspy xsd生成java_XmlSpy / XSD 以及 验证
  16. javaScript中的垃圾回收机制
  17. 查询GPU时无进程运行,但是显存却被占用了
  18. Windows 7(Win7)下Visual Studio 2012(VS2012)编译jrtplib与MinGW编译jrtplib
  19. fiilt1左耳无法同步_FIIL T1 X真无线运动耳机体验:闪连快充秒同步 媲美AirPods
  20. 202009-4 星际旅行

热门文章

  1. 曾经的独角兽 Docker,如今资金紧张
  2. 如何使用Visual Studio无需成本即可实现连续集成
  3. MFC关闭对话框可以不析构吗_Win10关闭Defender和防火墙
  4. linux 编辑启动菜单,grub2的配置,linux启动菜单修改
  5. 云南省计算机专业技术,云南省2018年下半年全国计算机技术与软件专业技术资格(水平)考试顺利举行...
  6. mysql 建立索引_mysql建立索引的原则
  7. 王者荣耀4月14日服务器维护,王者荣耀4月14日更新了什么内容?4月14日更新内容介绍...
  8. jersey2.22.2异常java.lang.NoSuchMethodError: org.glassfish.jersey.CommonProperties.getValue
  9. mysql group by top_Mysql group by top N的问题 | 学步园
  10. 计算机无法从硬盘启动怎么办,电脑不能从硬盘启动应该怎么解决