[luogu 5024] 保卫王国
Problem Here
Solution
这大概是一篇重复累赘的blog吧。
最小权覆盖集=全集-最大权独立集
强制取或不取,可以通过将权值修改成inf或者-inf
然后就用动态dp的套路就行了
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define MN 100005
#define inf 1000000005
int n,m,v[MN];
struct edge{int to,nex;}e[MN<<1];
int hr[MN],en;
std::set<int> mp[MN];
inline void ins(int f,int t)
{
mp[f].insert(t);
mp[t].insert(f);
e[++en]=(edge){t,hr[f]};hr[f]=en;
e[++en]=(edge){f,hr[t]};hr[t]=en;
}
int mx[MN],siz[MN],top[MN],fa[MN];
void dfs1(int x,int f)
{
siz[x]=1;fa[x]=f;register int i;
for(i=hr[x];i;i=e[i].nex)if(f^e[i].to)
{
dfs1(e[i].to,x);siz[x]+=siz[e[i].to];
if(siz[e[i].to]>siz[mx[x]]) mx[x]=e[i].to;
}
}
void dfs2(int x,int f,int tp)
{
top[x]=tp;if(mx[x]) dfs2(mx[x],x,tp);
register int i;
for(i=hr[x];i;i=e[i].nex)if((e[i].to^f)&&(e[i].to^mx[x])) dfs2(e[i].to,x,e[i].to);
}
struct matrix
{
ll a[2][2];
matrix(){memset(a,0,sizeof a);}
matrix operator * (const matrix &b) const
{
register matrix c;register int i,j,k;
for(i=0;i<2;++i)for(j=0;j<2;j++)for(k=0;k<2;++k)
c.a[i][j]=max(c.a[i][j],b.a[i][k]+a[k][j]);
return c;
}
}t[MN<<2],Ans;
ll g[MN][2],f[MN][2],sum;
int pos[MN],id[MN],dind,st[MN];
void init(int x,int F)
{
register int i;g[x][1]=(ll)v[x];
for(i=hr[x];i;i=e[i].nex)
if((e[i].to^F)&&(e[i].to^mx[x]))
{
init(e[i].to,x);
g[x][0]+=max(f[e[i].to][0],f[e[i].to][1]);
g[x][1]+=f[e[i].to][0];
}
f[x][0]=g[x][0];f[x][1]=g[x][1];
if(mx[x])
{
init(mx[x],x);
f[x][0]+=max(f[mx[x]][0],f[mx[x]][1]);
f[x][1]+=f[mx[x]][0];
}
pos[x]=++dind;id[dind]=x;
if(st[top[x]]==0) st[top[x]]=dind;
}
#define mid ((l+r)>>1)
void build(int k,int l,int r)
{
if(l==r)
{
t[k].a[0][0]=t[k].a[0][1]=g[id[l]][0];
t[k].a[1][0]=g[id[l]][1];t[k].a[1][1]=0ll;
return;
}
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
t[k]=t[k<<1]*t[k<<1|1];
}
void Modify(int k,int l,int r,int x)
{
if(l==r)
{
t[k].a[0][0]=t[k].a[0][1]=g[id[l]][0];
t[k].a[1][0]=g[id[l]][1];t[k].a[1][1]=0ll;
return;
}
if(x<=mid) Modify(k<<1,l,mid,x);
else Modify(k<<1|1,mid+1,r,x);
t[k]=t[k<<1]*t[k<<1|1];
}
matrix query(int k,int l,int r,int a,int b)
{
if(l==a&&r==b) return t[k];
if(b<=mid) return query(k<<1,l,mid,a,b);
if(a>mid) return query(k<<1|1,mid+1,r,a,b);
return query(k<<1,l,mid,a,mid)*query(k<<1|1,mid+1,r,mid+1,b);
}
ll Que()
{
Ans=query(1,1,n,st[1],pos[1]);
return max(Ans.a[0][0],Ans.a[1][0]);
}
inline void change(int x,ll add)
{
g[x][1]+=add;
while(x!=0){
Modify(1,1,n,pos[x]);
matrix tmp=query(1,1,n,st[top[x]],pos[top[x]]);
ll f0=tmp.a[0][0],f1=tmp.a[1][0];
if(top[x]!=1){
g[fa[top[x]]][1]+=f0-f[top[x]][0];
g[fa[top[x]]][0]+=max(f1,f0)-max(f[top[x]][0],f[top[x]][1]);
}
f[top[x]][0]=f0;f[top[x]][1]=f1;
x=fa[top[x]];
}
}
int main()
{
register char ch[5];
n=read(),m=read();scanf("%s",ch+1);
register int i,j,a,b;
for(i=1;i<=n;i++) v[i]=read(),sum+=1ll*v[i];
for(i=1;i<n;i++) j=read(),ins(j,read());
dfs1(1,0);dfs2(1,0,1);init(1,0);build(1,1,n);
while(m--)
{
i=read();j=read();a=read(),b=read();
if(j==0&&b==0&&mp[i].count(a))
{
puts("-1");
continue;
}
change(i,(j==0?1:-1)*inf);
change(a,(b==0?1:-1)*inf);
printf("%lld\n",sum-Que()+1ll*(j==0?1:0)*inf+1ll*(b==0?1:0)*inf);
change(i,(j==0?-1:1)*inf);
change(a,(b==0?-1:1)*inf);
}
return 0;
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
[luogu 5024] 保卫王国的更多相关文章
- [倍增][换根DP]luogu P5024 保卫王国
题面 https://www.luogu.com.cn/problem/P5024 分析 可以对有限制的点对之间的链进行在倍增上的DP数组合并. 需要通过一次正向树形DP和一次换根DP得到g[0][i ...
- 洛谷5024 保卫王国 (动态dp)
qwq非正解. 但是能跑过. 1e5 log方还是很稳的啊 首先,考虑最普通的\(dp\) 令\(dp1[x][0]表示不选这个点,dp1[x][1]表示选这个点的最大最小花费\) 那么 \(dp1[ ...
- [NOIP2018TG]保卫王国
[NOIP2018TG]保卫王国 BZOJ luogu 当动态dp模板题写的,(全集-最大点权独立集)不能放军队的+inf,必须放军队-inf即可 注意矩阵乘法的顺序问题 #define ll lon ...
- noip2018 d2t3 保卫王国 解题报告
保卫王国 电脑卡懒得把题面挪过来了. 朴素 \[ dp_{i,0}=\sum dp_{s,1}\\ dp_{i,1}=\sum \min(dp_{s,0},dp_{s,1})+p_i \] 然后直接动 ...
- LG5024 保卫王国
题意 题目描述 Z 国有\(n\)座城市,\(n - 1\)条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻扎军队.驻扎军队需要 ...
- 「NOIP2018」保卫王国
「NOIP2018保卫王国」 题目描述 有一棵 \(n\) 个点, 点有点权 \(a_i\),\(m\) 组询问, 每次求钦点两个节点必须选或者必须不选后的树上最小点覆盖. \(1 \leq n, m ...
- Uoj 441 保卫王国
Uoj 441 保卫王国 动态 \(dp\) .今天才来写这个题. 设 \(f[u][0/1]\) 表示子树 \(u\) 中不选/选 \(u\) 时的最小权值和,显然有:\(f[u][0]=\sum ...
- 竞赛题解 - NOIP2018 保卫王国
\(\mathcal{NOIP2018}\) 保卫王国 - 竞赛题解 按某一个炒鸡dalao名曰 taotao 的话说: \(\ \ \ \ \ \ \ \ \ "一道sb倍增题" ...
- 『保卫王国 树上倍增dp』
保卫王国 Description Z 国有n座城市,n - 1条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻扎军队.驻扎军队需 ...
随机推荐
- 扩展JS
//JS的扩展方法: 1 定义类静态方法扩展 2 定义类对象方法扩展 var aClass = function(){} //1 定义这个类的静态方法 aC ...
- vue中v-if和v-for指令最好不要同时使用
建议不要在与v-for相同的元素上使用v-if.因为v-for指令的优先级高于v-if当它们处于同一节点.v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for ...
- 如何在SAP Cloud Platform ABAP编程环境里创建一个employee
用ABAP Development Tool登录SAP Cloud Platform ABAP编程环境后,对ABAP项目点击右键,选择属性,从而找到该环境的web访问的url: https://325 ...
- Topshelf+Quartz实现windows任务
Topshelf使用示例, HostFactory.Run(x => { x.Service<QuartzStartup>(s => { s.ConstructUsing(na ...
- Centos7 docker安装GitLab
*先决条件系统已安装Docker 1.查询GitLab镜像 docker search gitlab 2.现在GitLab镜像 3.创建文件夹 mkdir -p /software/gitlab/co ...
- 【hadoop】在eclipse上运行WordCount的操作过程
序:本以为今天花点时间将WordCount例子完全理解到,但高估自己了,更别说我只是在大学选修一学期的java,之后再也没碰过java语言了 总的来说,从宏观上能理解具体的程序思路,但具体到每个代码有 ...
- Linux kernel启动选项(参数)
在Linux中,给kernel传递参数以控制其行为总共有三种方法: 1.build kernel之时的各个configuration选项. 2.当kernel启动之时,可以参数在kernel被GRUB ...
- SCADA系统构架的安全分析总结
概念: SCADA 数据采集与监控 Supervisory Control And Data Acquisition .包括了计算机设备 工业控制组件 网络 组成部件 ,SCADA 系统被用 ...
- 宁波市第二届CTF部分WP之msc1,msc2
msc1签到 这题没啥好说的,修改一下图片宽高,flag到手 msc2 一开始用十六进制编辑器打开,分析文件,暂时无果,卡了一小时(线下没网) 后面,看着这部分文件头眼熟,猜测是GIF头, 于是,在硬 ...
- 复习巩固:oracle如何实现去重和分页
一:oracle实现去重: user数据表: 分两步:1.查询重复数据 2.删除重复数据 1.查询重复数据:在oracle中实现查询重复数据,可以借助于rowid这个伪列.oracle中每个表物理上 ...