NOIP2018保卫王国
题目大意:给一颗有点权的树,每次规定两个点选还是不选,求这棵树的最小权点覆盖。
题解
ZZ码农题。
要用动态dp做,这题就是板子,然鹅并不会,留坑代填。
因为没有修改,所以可以静态倍增。
我们先做一遍正常的树形dp,求出g[i][0/1],0/1表示当前节点选或不选。
然后我们再倒腾出一个数组l[i][0/1]表示从当前点作为根,再扣掉当前子树的答案。
然后倍增处理dp[i][j][0/1][0/1]表示从i向上2i长度的链,起点和终点的选择情况,表示以下区域的答案。
比如这条黑色的链,它表示的是黄圈里的所有点的答案。
然后对于一个询问,我们可以跳LCA,边跳变统计答案,这样我们就可以统计出以LCA为根的子树的答案,在加上之前处理过的l数组的答案,就可以吧答案算全了。
NOIP考这种****题有意思吗?
代码
#include<iostream>
#include<cstdio>
#define N 100009
using namespace std;
typedef long long ll;
int tot,head[N],deep[N],p[N][],n,m;
char typef[];
ll dp[N][][][],w[N],f[][],g[][],pr[N][],lian[N][],pr2[N][];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct node{int n,to;}e[N<<];
inline void add(int u,int v){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;}
inline void hb(int x,int y,int l){
dp[x][l][][]=min(dp[x][l-][][]+dp[y][l-][][],dp[x][l-][][]+dp[y][l-][][]);
dp[x][l][][]=min(dp[x][l-][][]+dp[y][l-][][],dp[x][l-][][]+dp[y][l-][][]);
dp[x][l][][]=min(dp[x][l-][][]+dp[y][l-][][],dp[x][l-][][]+dp[y][l-][][]);
dp[x][l][][]=min(dp[x][l-][][]+dp[y][l-][][],dp[x][l-][][]+dp[y][l-][][]);
}
void dfs(int u,int fa){
for(int i=;(<<i)<=deep[u];++i){
p[u][i]=p[p[u][i-]][i-];
hb(u,p[u][i-],i);
}
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;deep[v]=deep[u]+;p[v][]=u;
dp[v][][][]=pr[u][]-min(pr[v][],pr[v][]);
dp[v][][][]=pr[u][]-pr[v][];
dp[v][][][]=pr[u][]-min(pr[v][],pr[v][]);
dfs(v,u);
}
}
void predfs(int u,int fa){
pr[u][]=;pr[u][]=w[u];
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;predfs(v,u);
pr[u][]+=pr[v][];pr[u][]+=min(pr[v][],pr[v][]);
}
}
void dfs2(int u,int fa){
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;
// pr2[v][0]=pr2[u][1];pr2[v][1]=min(pr2[u][0],pr2[u][1]);
// lian[v][0]=pr2[v][0]-pr[v][0];lian[v][1]=pr2[v][1]-pr[v][1];
lian[v][]=lian[u][]+pr[u][]-min(pr[v][],pr[v][]);
lian[v][]=min(lian[v][],lian[u][]+pr[u][]-pr[v][]);
dfs2(v,u);
}
}
inline ll getlca(int a,int b,int x,int y){
if(deep[a]<deep[b])swap(a,b),swap(x,y);
// cout<<a<<" "<<b<<" "<<x<<" "<<y<<endl;
ll ans=pr[a][x]; //cout<<ans<<endl;
f[][x]=;int now=,pre=;
for(int i=;i>=;--i)if(deep[a]-(<<i)>=deep[b]){
f[now][]=min(f[pre][]+dp[a][i][][],f[pre][]+dp[a][i][][]);
f[now][]=min(f[pre][]+dp[a][i][][],f[pre][]+dp[a][i][][]);
swap(now,pre);a=p[a][i];
}
if(a==b)return ans+f[pre][y]+lian[a][y];
g[pre][y]=;ans+=pr[b][y];//cout<<ans<<endl;
for(int i=;i>=;--i)if(p[a][i]!=p[b][i]){
f[now][]=min(f[pre][]+dp[a][i][][],f[pre][]+dp[a][i][][]);
f[now][]=min(f[pre][]+dp[a][i][][],f[pre][]+dp[a][i][][]);
g[now][]=min(g[pre][]+dp[b][i][][],g[pre][]+dp[b][i][][]);
g[now][]=min(g[pre][]+dp[b][i][][],g[pre][]+dp[b][i][][]);
swap(now,pre);a=p[a][i];b=p[b][i];
}
swap(now,pre);
ll ans1=f[now][]+g[now][]+pr[p[a][]][]-pr[a][]-pr[b][];
ll ans2=min(f[now][],f[now][])+min(g[now][],g[now][])+pr[p[a][]][]-min(pr[a][],pr[a][])-min(pr[b][],pr[b][]);
return ans+min(ans1+lian[p[a][]][],ans2+lian[p[a][]][]);
}
int main(){
n=rd();m=rd();scanf("%s",typef);int u,v;
for(int i=;i<=n;++i)w[i]=rd();
for(int i=;i<=n;++i)
for(int j=;j<=;++j)
for(int k=;k<=;++k)for(int l=;l<=;++l)dp[i][j][k][l]=1e12;
for(int i=;i<n;++i){u=rd();v=rd();add(u,v);add(v,u);}
predfs(,);
pr2[][]=pr[][];pr2[][]=pr[][];dfs2(,);
dfs(,);int a,x,b,y;
/* for(int i=1;i<=n;++i){
cout<<i<<" ";
for(int j=0;j<=1;++j)cout<<lian[i][j]<<" ";cout<<endl;
}*/
/* for(int i=1;i<=n;++i){
cout<<i<<endl;
for(int j=0;(1<<j)<=deep[i];++j)cout<<dp[i][j][0][0]<<" "<<dp[i][j][0][1]<<" "<<dp[i][j][1][0]<<" "<<dp[i][j][1][1]<<endl;
}*/
while(m--){
a=rd();x=rd();b=rd();y=rd();
for(int i=;i<=;++i)for(int j=;j<=;++j)f[i][j]=g[i][j]=1e12;
ll ans=getlca(a,b,x,y);
if(ans>1e10)puts("-1");else printf("%lld\n",ans);
}
return ;
}
NOIP2018保卫王国的更多相关文章
- 竞赛题解 - NOIP2018 保卫王国
\(\mathcal{NOIP2018}\) 保卫王国 - 竞赛题解 按某一个炒鸡dalao名曰 taotao 的话说: \(\ \ \ \ \ \ \ \ \ "一道sb倍增题" ...
- [NOIP2018]保卫王国 题解
NOIP2018提高组D2T3 ddp虽然好想,但是码量有点大(其实是我不会),因此本文用倍增优化树形DP来解决本题. 题意分析 给一棵树染色,每个节点染色需要一定的花费,要求相邻两个节点至少要有一个 ...
- 【比赛】NOIP2018 保卫王国
DDP模板题 #include<bits/stdc++.h> #define ui unsigned int #define ll long long #define db double ...
- luogu5024 [NOIp2018]保卫王国 (动态dp)
可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵 #include<bits/stdc++.h> #define CLR(a,x) memset(a ...
- 2019.02.16 bzoj5466: [Noip2018]保卫王国(链分治+ddp)
传送门 题意简述: mmm次询问,每次规定两个点必须选或者不选,求树上的带权最小覆盖. 思路: 考虑链分治+ddpddpddp 仍然是熟悉的套路,先考虑没有修改的状态和转移: 令fi,0/1f_{i, ...
- [NOIP2018]保卫王国
嘟嘟嘟 由于一些知道的人所知道的,不知道的人所不知道的原因,我来发NOIP2018day2T3的题解了. (好像我只是个搬运工--) 这题真可以叫做NOIplus了,跟其他几道比较水的题果然不一样,无 ...
- [NOIP2018]保卫王国(树形dp+倍增)
我的倍增解法吊打动态 \(dp\) 全局平衡二叉树没学过 先讲 \(NOIP\) 范围内的倍增解法. 我们先考虑只有一个点取/不取怎么做. \(f[x][0/1]\) 表示取/不取 \(x\) 后,\ ...
- 「NOIP2018 保卫王国」
题目 强制选点我们可以把那个点权搞成\(-inf\),强制不选我们搞成\(inf\),之后就真的成为动态\(dp\)的板子题了 由于不想像板子那样再写一个最大独立集的方程,之后利用最小点覆盖=总点权- ...
- BZOJ5466 NOIP2018保卫王国(倍增+树形dp)
暴力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]). 注意到 ...
随机推荐
- mysql常用命令行操作(二):表和库的操作、引擎、聚合函数
一.查看.创建.删除数据库 create database library default character set utf8 collate utf8_general_ci; # 创建数据库并设置 ...
- MySQL 性能调优之索引
原文:http://bbs.landingbj.com/t-0-245452-1.html 对于索引的优化,我们第一需要找到合适的字段,第二创建索引找到合适的顺序,第三要找到合适的比例,第四是要做合适 ...
- Web移动端---iPhone X适配(底部栏黑横线)
一.相信大家有被iPhone X底部黑色横线支配的恐惧 上面我们可以看到,底部的导航栏被一条黑色横线所盖住,那么就很烦.下面我们可以开始进行适配环节 1.首先我们可以用 JS 判断手机环境是不是 iP ...
- Dart语法基础
hello world // Define a function. printNumber(num aNumber) { print('The number is $aNumber.'); // Pr ...
- 牛客练习赛13E 乌龟跑步
题目链接:https://ac.nowcoder.com/acm/contest/70/E 题目大意: 略 分析: DP或记忆化搜索,个人觉得记忆化搜索比较好做,逻辑清晰,代码量少 代码如下: #in ...
- awk骚操作
一.awk自加 [root@168web3 ~]# head /data/logs/cloud_monitor_rds_cpu.log |awk '{sum+=$NF}END{print sum}' ...
- saltstack二
配置管理 haproxy的安装部署 haproxy各版本安装包下载路径https://www.haproxy.org/download/1.6/src/,跳转地址为http,改为https即可 创建相 ...
- 今日头条移动app广告激活数据API对接完整Java代码实现供大家参考》》》项目随记
这是自毕业后的第一篇博客,希望自己今后能养成写博客的一个好习惯.最近公司为了加速APP推广,采取在外部平台(如:今日头条)进行广告投放的方式,进行用户引流.因此我们需要对广告的激活数据进行一个检测,跟 ...
- linux按时间查询日志
在系统应用集中部署的时候,很多日志因为太多难以定位,获取某段时间的日志是对运维人员非常关键的事情. 一.sed查看某时间段到现在的系统日志: sed -n '/May 20 17/,$p' / ...
- jedis集群版应用
1.pom文件添加依赖: 2.创建配置文件 <!-- jedis集群版配置(JedisCluster通过构造传参(2个参数)) --> <bean id="redisCli ...