题意

求最小权值点覆盖。

mmm次询问,每次给出两个点,分别要求每个点必须选或必须不选,输出每次的最小权值覆盖或者无解输出−1-1−1

题解

强制选或者不选可以看做修改权值为±∞\pm\infin±∞。

那么就是这道板题了。

CODE

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<class T>inline void read(T &x) {
char ch; int flg=1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0'); x*=flg;
}
const int MAXN = 100005;
const LL INF = 1e10;
int n, m, fir[MAXN], nxt[MAXN<<1], to[MAXN<<1], cnt; LL V[MAXN];
inline void link(int u, int v) {
to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt;
to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt;
}
int tmr, fa[MAXN], dfn[MAXN], tp[MAXN], bt[MAXN], son[MAXN], sz[MAXN], seq[MAXN];
struct mat {
LL a[2][2];
LL* operator[](int x) { return a[x]; }
mat operator*(const mat &o)const {
mat re;
for(int i = 0; i < 2; ++i)
for(int j = 0; j < 2; ++j)
re.a[i][j] = min(a[i][0]+o.a[0][j], a[i][1]+o.a[1][j]);
return re;
}
}t[MAXN<<2], val[MAXN];
void dfs1(int u, int ff) {
fa[u] = ff; sz[u] = 1;
for(int i = fir[u], v; i; i = nxt[i])
if((v=to[i]) != ff) {
dfs1(v, u), sz[u] += sz[v];
(sz[v] > sz[son[u]]) && (son[u] = v);
}
}
LL f[MAXN][2];
void dfs2(int u, int top) {
tp[u] = top; bt[top] = u;
seq[dfn[u]=++tmr] = u;
if(son[u]) dfs2(son[u], top);
for(int i = fir[u], v; i; i = nxt[i])
if((v=to[i]) != fa[u] && v != son[u])
dfs2(v, v);
}
void dp(int u) {
f[u][0] = V[u]; f[u][1] = 0;
for(int i = fir[u], v; i; i = nxt[i])
if((v=to[i]) != fa[u])
dp(v),
f[u][0] += min(f[v][0], f[v][1]),
f[u][1] += f[v][0];
}
void build(int i, int l, int r) {
if(l == r) {
LL f0 = V[seq[l]], f1 = 0;
for(int j = fir[seq[l]], v; j; j = nxt[j])
if((v=to[j]) != fa[seq[l]] && v != son[seq[l]])
f0 += min(f[v][0], f[v][1]),
f1 += f[v][0];
val[l] = t[i] = (mat){ {{f0, f0} , {f1, INF}} };
return;
}
int mid = (l + r) >> 1;
build(i<<1, l, mid);
build(i<<1|1, mid+1, r);
t[i] = t[i<<1] * t[i<<1|1];
}
void update(int i, int l, int r, int x) {
if(l == r) { t[i] = val[l]; return; }
int mid = (l + r) >> 1;
if(x <= mid) update(i<<1, l, mid, x);
else update(i<<1|1, mid+1, r, x);
t[i] = t[i<<1] * t[i<<1|1];
}
mat query(int i, int l, int r, int x, int y) {
if(x == l && r == y) return t[i];
int mid = (l + r) >> 1;
if(y <= mid) return query(i<<1, l, mid, x, y);
if(x > mid) return query(i<<1|1, mid+1, r, x, y);
return query(i<<1, l, mid, x, mid) * query(i<<1|1, mid+1, r, mid+1, y);
}
void modify(int u, LL W) {
val[dfn[u]][0][0] += W-V[u];
val[dfn[u]][0][1] += W-V[u];
V[u]=W;
while(u) {
mat pre = query(1, 1, n, dfn[tp[u]], dfn[bt[tp[u]]]);
update(1, 1, n, dfn[u]);
mat now = query(1, 1, n, dfn[tp[u]], dfn[bt[tp[u]]]);
u = fa[tp[u]]; if(!u) return; int x = dfn[u];
LL p0 = pre[0][0], p1 = pre[1][0];
LL n0 = now[0][0], n1 = now[1][0];
val[x][0][0] = val[x][0][1] = val[x][0][0] + min(n0, n1) - min(p0, p1);
val[x][1][0] = val[x][1][0] + n0 - p0;
}
}
map<pair<int,int>, bool>E;
char s[10];
int main () {
read(n), read(m); scanf("%s", s);
for(int i = 1; i <= n; ++i) read(V[i]);
for(int i = 1, u, v; i < n; ++i) read(u), read(v), link(u, v), E[pair<int,int>(min(u,v), max(u,v))] = 1;
dfs1(1, 0), dfs2(1, 1), dp(1);
build(1, 1, n);
int a, x, b, y;
while(m--) {
read(a), read(x), read(b), read(y);
if(!x && !y && E.count(pair<int,int>(min(a,b), max(a,b)))) {
puts("-1"); continue;
}
LL sum = 0;
LL tmpa = V[a]; modify(a, V[a] + (x ? -INF : INF)); sum += (x ? -INF : 0);
LL tmpb = V[b]; modify(b, V[b] + (y ? -INF : INF)); sum += (y ? -INF : 0);
mat ans = query(1, 1, n, 1, dfn[bt[1]]);
printf("%lld\n", min(ans[0][0], ans[1][0])-sum);
modify(a, tmpa), modify(b, tmpb);
}
}

NOIP2018 保卫王国(动态DP)的更多相关文章

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

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

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

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

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

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

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

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

  5. luoguP5024 保卫王国 动态dp

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

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

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

  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. 竞赛题解 - NOIP2018 保卫王国

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

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

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

  10. NOIP2018保卫王国

    题目大意:给一颗有点权的树,每次规定两个点选还是不选,求这棵树的最小权点覆盖. 题解 ZZ码农题. 要用动态dp做,这题就是板子,然鹅并不会,留坑代填. 因为没有修改,所以可以静态倍增. 我们先做一遍 ...

随机推荐

  1. C++中数组占用的内存计算

    在C++中int类型每个空间是4个字节,long long int 是8个字节,而bool类型是1个字节 所以一般能用bool就别用int,节约空间 数组占用内存的计算 a[1001][1001]的空 ...

  2. PHP get和post向服务器发送请求

    1 .get请求 <?php //请求url地址 $token="xxx"; $url = "请求的地址"; //初始化curl $ch = curl_i ...

  3. python 之 面向对象基础(组合和封装)

    7.4 组合 解决类与类之间代码冗余问题有两种解决方案: 1.继承:描述的是类与类之间,什么是什么的关系 2.组合:描述的是类与类之间的关系,是一种什么有什么的关系 一个类产生的对象,该对象拥有一个属 ...

  4. h5开发微信公众号重定向到关注页面没有关注按钮 (微信你个坑)

    搜索微信公众号是这样的 微信公众号重定向到关注页面没有关注按钮 如何微信公众号重定向到关注页面没有关注按钮,请看上篇笔记 无解,微信一直在封这种通过链接跳转到公众号关注页面的方法.只有放个二维码提示长 ...

  5. 微信公众号h5页面自定义分享

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. logback的使用和配置

    参考:https://www.cnblogs.com/warking/p/5710303.html https://www.cnblogs.com 一.logback简介 1.logback: Log ...

  7. python入门-windows下anaconda环境搭建

    1. anaconda下载 根据根据自己系统下载32位还是64位,还有版本 python3.6——64bit python3.6——32bit python2.7——64bit python2.7—— ...

  8. TortoiseSVN-1.7.12.24070-x64-svn-1.7.9安装包和汉化包

    链接:https://pan.baidu.com/s/1NbrQW44N_kTh7VN0Fz0zVA 提取码:nhd9 先安装TortoiseSVN-1.7.12.24070-x64-svn-1.7. ...

  9. 【转载】Sqlserver使用SUBSTRING函数截取字符串

    在SQL语句查询过程中,Sqlserver支持使用LEFT().RIGHT().SUBSTRING()等几个函数对字符串进行截取操作,SubString函数相对于其他两个函数来说更灵活,使用场景更多, ...

  10. 【转载】使用Response.WriteFile输出文件以及图片

    Response对象是Asp.Net应用程序中非常重要的一个内置对象,其作用为负责将服务器执行好的信息输出给客户端,可以使用Response.WriteFile方法来像客户端输出文件或者图片,输出图片 ...