qwq非正解。

但是能跑过。

1e5 log方还是很稳的啊

首先,考虑最普通的\(dp\)

令\(dp1[x][0]表示不选这个点,dp1[x][1]表示选这个点的最大最小花费\)

那么

\(dp1[x][0]=\sum dp[p][1]\)

\(dp1[x][1]=\sum min(dp[p][1],dp[p][0])+val[x]\)

根据套路,我们要树链剖分+改变\(dp\)数组,我们令\(f[x]\)表示忽略重儿子的\(dp\)值,用\(g\)表示正常的\(dp\)值的话

那么不难发现转移矩阵应该是

{g[p][0],g[p][1]}

乘上

inf f[x][1]
f[x][0] f[x][1]

等于

g[x][0] g[x][1]

qwq

然后其他的就是动态dp的部分了

但是需要注意的一个地方是。

你如果通过写一个类似的\(modify\)

void modify(int x,Ju y)
{
update(1,1,n,newnum[x],y);
for (int now=top[x];now!=1;now=top[now])
{
int faa = fa[now];
Ju ymh = query(1,1,n,newnum[faa],newnum[faa]);
Ju lyf = query(1,1,n,newnum[now],newnum[tail[top[now]]]);
ymh.a[1][2]+=min(lyf.a[1][2],lyf.a[1][1]) - min(pre[now].a[1][2],pre[now].a[1][1]);
ymh.a[2][2]=ymh.a[1][2];
ymh.a[2][1]+=lyf.a[1][2]-pre[now].a[1][2];
if (faa==tail[top[faa]]) ymh.a[1][1]=ymh.a[2][1];
update(1,1,n,newnum[faa],ymh);
pre[now]=lyf;
now = fa[now];
}
}

你需要\(modify\)三次,才可以。因为你第一次\(modify\)实际上是基于另一个不还原的前提下来还原第一个,但是实际上,我们是要求在另一个还原过的基础上还原第一个。

但是如果你用如下的函数进行还原的话

void wei(int x)
{
update(1,1,n,newnum[x],ymh[x]);
for (int now = top[x];now!=1;now=top[now])
{
int faa = fa[now];
update(1,1,n,newnum[faa],ymh[faa]);
pre[now]=bre[now];
now=fa[now];
}
}

直接给代码

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define pb push_back
#define mk make_pair
#define ll long long
#define lson ch[x][0]
#define rson ch[x][1] using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 2e5+1e2;
const int maxm = 2*maxn;
const ll inf = 1e18; struct Ju{
int x,y;
ll a[3][3];
Ju operator * (Ju b)
{
Ju ans;
ans.x=2;
ans.y=2;
memset(ans.a,127/3,sizeof(ans.a));
for (int i=1;i<=2;i++)
{
for (int j=1;j<=2;j++)
for (int k=1;k<=2;k++)
{
ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
}
}
return ans;
}
}; Ju f[4*maxn];
Ju pre[maxn];
int point[maxn],nxt[maxm],to[maxm];
int cnt,n,m,q;
ll val[maxn],dp1[maxn][2],dp[maxn][2];
Ju ymh[maxn];
int fa[maxn],size[maxn],son[maxn],back[maxn],newnum[maxn];
int tail[maxn],top[maxn]; void addedge(int x,int y)
{
nxt[++cnt]=point[x];
to[cnt]=y;
point[x]=cnt;
} void up(int root)
{
f[root]=f[2*root+1]*f[2*root];
} Ju bre[maxn]; void build(int root,int l,int r)
{
if (l==r)
{
int now = back[l];
f[root].x=f[root].y=2;
if (tail[top[now]]==now)
{
f[root].a[1][1]=dp[now][0];
f[root].a[1][2]=dp[now][1];
f[root].a[2][1]=f[root].a[1][1];
f[root].a[2][2]=f[root].a[1][2];
}
else
{
f[root].a[1][1]=inf;
f[root].a[1][2]=dp[now][1];
f[root].a[2][1]=dp[now][0];
f[root].a[2][2]=dp[now][1];
}
ymh[now]=f[root];
return;
}
int mid = l+r >> 1;
build(2*root,l,mid);
build(2*root+1,mid+1,r);
up(root);
} void update(int root,int l,int r,int x,Ju p)
{
if(l==r)
{
f[root]=p;
return;
}
int mid = l+r >> 1;
if (x<=mid) update(2*root,l,mid,x,p);
else update(2*root+1,mid+1,r,x,p);
up(root);
} Ju query(int root,int l,int r,int x,int y)
{
if (x<=l && r<=y) return f[root];
int mid = l+r>>1;
if (y<=mid) return query(2*root,l,mid,x,y);
if (x>mid) return query(2*root+1,mid+1,r,x,y);
return query(2*root+1,mid+1,r,x,y)*query(2*root,l,mid,x,y);
} void dfs1(int x,int faa)
{
size[x]=1;
int maxson=-1;
for (int i=point[x];i;i=nxt[i])
{
int p = to[i];
if (p==faa) continue;
fa[p]=x;
dfs1(p,x);
size[x]+=size[p];
if (size[p]>maxson)
{
maxson=size[p];
son[x]=p;
}
}
} int tot; void dfs2(int x,int chain)
{
top[x]=chain;
tail[chain]=x;
newnum[x]=++tot;
back[tot]=x;
if (!son[x]) return;
dfs2(son[x],chain);
for (int i=point[x];i;i=nxt[i])
{
int p = to[i];
if (!newnum[p]) dfs2(p,p);
}
} void solve(int x,int fa)
{
dp1[x][1]=dp[x][1]=val[x];
for (int i=point[x];i;i=nxt[i])
{
int p = to[i];
if (p==fa) continue;
solve(p,x);
dp1[x][0]=dp1[x][0]+dp1[p][1];
dp1[x][1]=dp1[x][1]+min(dp1[p][0],dp1[p][1]);
if (p!=son[x])
{
dp[x][0]=dp[x][0]+dp1[p][1];
dp[x][1]=dp[x][1]+min(dp1[p][0],dp1[p][1]);
}
}
} int uu; void modify(int x,Ju y)
{
update(1,1,n,newnum[x],y);
for (int now=top[x];now!=1;now=top[now])
{
int faa = fa[now];
Ju ymh = query(1,1,n,newnum[faa],newnum[faa]);
Ju lyf = query(1,1,n,newnum[now],newnum[tail[top[now]]]);
ymh.a[1][2]+=min(lyf.a[1][2],lyf.a[1][1]) - min(pre[now].a[1][2],pre[now].a[1][1]);
ymh.a[2][2]=ymh.a[1][2];
ymh.a[2][1]+=lyf.a[1][2]-pre[now].a[1][2];
if (faa==tail[top[faa]]) ymh.a[1][1]=ymh.a[2][1];
update(1,1,n,newnum[faa],ymh);
pre[now]=lyf;
now = fa[now];
}
} void wei(int x)
{
update(1,1,n,newnum[x],ymh[x]);
for (int now = top[x];now!=1;now=top[now])
{
int faa = fa[now];
update(1,1,n,newnum[faa],ymh[faa]);
pre[now]=bre[now];
now=fa[now];
}
}
signed main()
{
n=read();m=read(),uu=read();
for (int i=1;i<=n;i++) val[i]=read();
for (int i=1;i<n;i++)
{
int x=read(),y=read();
addedge(x,y);
addedge(y,x);
}
dfs1(1,0);
dfs2(1,1);
solve(1,0);
build(1,1,n);
for (int i=1;i<=n;i++)
{
pre[i]=query(1,1,n,newnum[i],newnum[tail[top[i]]]);
// cout<<i<<" "<<pre[i].a[1][1]<<" "<<pre[i].a[1][2]<<endl;
bre[i]=pre[i];
}
for (int i=1;i<=m;i++)
{
int a=read(),x=read(),b=read(),y=read();
Ju tmp = query(1,1,n,newnum[a],newnum[a]);
if (x==0)
{
if (a!=tail[top[a]])
{
tmp.a[1][2]=inf;
tmp.a[2][2]=inf;
}
else
{
tmp.a[1][2]=inf;
tmp.a[2][2]=inf;
}
}
else
{
if (a!=tail[top[a]])
tmp.a[2][1]=inf;
else tmp.a[1][1]=tmp.a[2][1]=inf;
}
modify(a,tmp);
tmp = query(1,1,n,newnum[b],newnum[b]);
if (y==0)
{
tmp.a[1][2]=tmp.a[2][2]=inf;
}
else
{
if (b!=tail[top[b]])
tmp.a[2][1]=inf;
else tmp.a[1][1]=tmp.a[2][1]=inf;
}
modify(b,tmp);
Ju now = query(1,1,n,newnum[1],newnum[tail[top[1]]]);
ll ptx = min(now.a[1][1],now.a[1][2]);
if (ptx>=inf) ptx=-1;
cout<<ptx<<"\n";
modify(a,ymh[a]);
modify(b,ymh[b]);
//wei(a);
//wei(b);
modify(a,ymh[a]);
}
return 0;
}

洛谷5024 保卫王国 (动态dp)的更多相关文章

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

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

  2. JZOJ5966. [NOIP2018TGD2T3] 保卫王国 (动态DP做法)

    题目大意 这还不是人尽皆知? 有一棵树, 每个节点放军队的代价是\(a_i\), 一条边连接的两个点至少有一个要放军队, 还有\(q\)次询问, 每次规定其中的两个一定需要/不可放置军队, 问这样修改 ...

  3. 【NOIP2018】保卫王国 动态dp

    此题场上打了一个正确的$44pts$,接着看错题疯狂$rush$“正确”的$44pts$,后来没$rush$完没将之前的代码$copy$回去,直接变零分了..... 这一题我们显然有一种$O(nm)$ ...

  4. luoguP5024 保卫王国 动态dp

    题目大意: emmmmm 题解: QAQ #include <cstdio> #include <cstring> #include <iostream> usin ...

  5. LuoguP5024 保卫王国(动态DP,LCT)

    最小权覆盖集 = 全集 - 最大权独立集 强制取点.不取点可以使用把权值改成正无穷或负无穷实现 接下来就是经典的"动态最大权独立集"了 O(nlogn). 这不是我说的,是immo ...

  6. BZOJ 5466: [Noip2018]保卫王国 动态DP

    Code: // luogu-judger-enable-o2 #include<bits/stdc++.h> #define ll long long #define lson (now ...

  7. P5024 保卫王国(动态dp/整体dp/倍增dp)

    做法(倍增) 最好写的一种 以下0为不选,1为选 \(f_{i,0/1}\)为\(i\)子树的最小值,\(g_{i,0/1}\)为除i子树外的最小值 \(fh_{i,j,0/1,0/1}\)为确定\( ...

  8. 洛谷P4475 巧克力王国

    洛谷P4475 巧克力王国 题目描述 巧克力王国里的巧克力都是由牛奶和可可做成的. 但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力. 对于每一块巧克力,我们设 x 和 y 为 ...

  9. 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)

    洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\)​​​​​.我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...

随机推荐

  1. leetcode——217. 存在重复元素

    leetcode--217. 存在重复元素 题目描述:给定一个整数数组,判断是否存在重复元素. 如果存在一值在数组中出现至少两次,函数返回 true .如果数组中每个元素都不相同,则返回 false ...

  2. MySQL存储结构及SQL分类

    MySQL目录结构 bin -- mysql执行程序 docs -- 文档 share - 各国编码信息 data -- 存放mysql 数据文件 * 每个数据库 创建一个同名文件夹,.frm 存放t ...

  3. 【Azure 应用服务】Python flask 应用部署在Aure App Service 遇见的 3 个问题

    在App Service(Windows)中部署Flask应用时的注意事项: ● 添加Python扩展插件,Python 3.6.4 x64: ●● 配置 FastCGI 处理程序,添加Web.con ...

  4. 人生重开模拟器「GitHub 热点速览 v.21.36」

    作者:HelloGitHub-小鱼干 人生是不能重来的,但是 lifeRestart 能满足你的重开心愿.初始值不满意,你可以一直随机生成或者自动添加颜值.智力.运气值,倒是一种"重生&qu ...

  5. AFL++初探-手把手Fuzz一个PDF解析器

    CVE-2019-13288 目前漏洞在正式版本已经被修复,本文章仅供学习Fuzz过程,不存在漏洞利用的内容 这是一个pdf查看器的漏洞,可能通过精心制作的文件导致无限递归,由于程序中每个被调用的函数 ...

  6. JVM详解(一)——概述

    Test https://www.cnblogs.com/yrxing/p/14651346.html#gc的基础知识 https://www.cnblogs.com/yinzhengjie/p/92 ...

  7. MySQL——字符集

    -- 字符集:是一个系统支持的所有抽象字符的集合 MySQL数据库的字符集(包括两个部分): 1.字符集:character 2.校对规则:collation MySQL中常见的字符集: utf8 l ...

  8. JS007. 深入探讨带浮点数运算丢失精度问题(二进制的浮点数存储方式)

    复现与概述 当JS在进行浮点数运算时可能产生丢失精度的情况: 从肉眼可见的程度上观察,发生精度丢失的浮点数是没有规律的,但该浮点数丢失精度的问题会100%复现.经查阅,这个问题要追溯至浮点数的二进制存 ...

  9. 【第十五篇】- Maven 依赖管理之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 依赖管理 Maven 一个核心的特性就是依赖管理.当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难.针对此种情形,Maven 提供了 ...

  10. RabbitMQie消息列队整理

    使用方法过程,这儿只做了windows平台教程 先安装Erlang 编程软件,然后设置环境变量,在安装RabbimMQ ,这儿我下载了一个版本不行,后来换了最新版就好了,以后在使用过程 中如果有问题 ...