题目大意:给一颗有点权的树,每次规定两个点选还是不选,求这棵树的最小权点覆盖。

题解

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保卫王国的更多相关文章

  1. 竞赛题解 - NOIP2018 保卫王国

    \(\mathcal{NOIP2018}\) 保卫王国 - 竞赛题解 按某一个炒鸡dalao名曰 taotao 的话说: \(\ \ \ \ \ \ \ \ \ "一道sb倍增题" ...

  2. [NOIP2018]保卫王国 题解

    NOIP2018提高组D2T3 ddp虽然好想,但是码量有点大(其实是我不会),因此本文用倍增优化树形DP来解决本题. 题意分析 给一棵树染色,每个节点染色需要一定的花费,要求相邻两个节点至少要有一个 ...

  3. 【比赛】NOIP2018 保卫王国

    DDP模板题 #include<bits/stdc++.h> #define ui unsigned int #define ll long long #define db double ...

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

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

  5. 2019.02.16 bzoj5466: [Noip2018]保卫王国(链分治+ddp)

    传送门 题意简述: mmm次询问,每次规定两个点必须选或者不选,求树上的带权最小覆盖. 思路: 考虑链分治+ddpddpddp 仍然是熟悉的套路,先考虑没有修改的状态和转移: 令fi,0/1f_{i, ...

  6. [NOIP2018]保卫王国

    嘟嘟嘟 由于一些知道的人所知道的,不知道的人所不知道的原因,我来发NOIP2018day2T3的题解了. (好像我只是个搬运工--) 这题真可以叫做NOIplus了,跟其他几道比较水的题果然不一样,无 ...

  7. [NOIP2018]保卫王国(树形dp+倍增)

    我的倍增解法吊打动态 \(dp\) 全局平衡二叉树没学过 先讲 \(NOIP\) 范围内的倍增解法. 我们先考虑只有一个点取/不取怎么做. \(f[x][0/1]\) 表示取/不取 \(x\) 后,\ ...

  8. 「NOIP2018 保卫王国」

    题目 强制选点我们可以把那个点权搞成\(-inf\),强制不选我们搞成\(inf\),之后就真的成为动态\(dp\)的板子题了 由于不想像板子那样再写一个最大独立集的方程,之后利用最小点覆盖=总点权- ...

  9. 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]). 注意到 ...

随机推荐

  1. Django 组件之 ----- content-type

    Django 组件之 content-type的使用 一个表和多个表进行关联,但具体随着业务的加深,表不断的增加,关联的数量不断的增加,怎么通过一开始通过表的设计后,不在后期在修改表,彻底的解决这个问 ...

  2. 敏捷与CMM的恩怨

    模式不同,一种是灵活,一种是严肃.

  3. Eclipse支持文件UTF-8编码

    Eclipse修改编码格式_百度经验https://jingyan.baidu.com/article/2009576193ee38cb0721b416.html 这篇最棒 如何为eclipse中的文 ...

  4. 二、npm scripts

    一.执行原理 安装npm 包,会将其package.json bin 字段添加到node_modules bin 里面,创建对应的.cmd文件,因此: 例如: "scripts": ...

  5. Windows NT 的历史

    Windows NT 的版本历史 https://blog.csdn.net/flyingpig2016/article/details/53282895/ 按照自己找到的资料:windows NT ...

  6. spring mvc常用注解总结

    1.@RequestMapping@RequestMappingRequestMapping是一个用来处理请求地址映射的注解(将请求映射到对应的控制器方法中),可用于类或方法上.用于类上,表示类中的所 ...

  7. display设置弹性盒布局

    转自:http://blog.csdn.net/itbwy/article/details/52648711 网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖  ...

  8. 收藏一个带动画效果的ScrollViewer以及ScrollBar的模板

    这里介绍一个带动画效果的ScrollViewer和ScrollBar,总共分为两个资源字典,直接拿来引用即可: 1 ScrollBarStyle.xaml <ResourceDictionary ...

  9. 从git中删除 .idea 目录

    将.idea目录加入ignore清单: $ echo '.idea' >> .gitignore   从git中删除idea: $ git rm —cached -r .idea 3 将. ...

  10. Maven 项目 无缘无故报错:版本冲突,其他机器上正常-提交的时候报冲突怎么也解决不掉

    2018年: maven突然之间报错了,显示版本冲突,但是其他的机器是好的, 使用命令:mvn compile -P dev -e; 看看测试环境有没有问题,还是有问题.而且,刚开始只是报错:erro ...