题目

强制选点我们可以把那个点权搞成\(-inf\),强制不选我们搞成\(inf\),之后就真的成为动态\(dp\)的板子题了

由于不想像板子那样再写一个最大独立集的方程,之后利用最小点覆盖=总点权-最大独立集的做法,而直接写了一个最小点覆盖的方程,所以写出了很多锅

  1. 矩阵里存放相同意义变量的位置可能真实值不相等,于是要取一个\(min\)

突然发现自己好像也没有写出多少锅,那就这样吧

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define mp std::make_pair
#define LL long long
#define re register
#define maxn 100005
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const LL inf=5e15;
const LL Inf=5e10;
typedef std::pair<int,int> pii;
std::map<pii,int> ma;
char opt[6];
struct E{int v,nxt;}e[maxn<<1];
struct mat{LL a[2][2];}d[maxn*4];
int n,m,num,__;
int l[maxn*4],r[maxn*4];
int sum[maxn],son[maxn],deep[maxn],head[maxn],top[maxn],bot[maxn];
LL dp[maxn][2],f[maxn][2];int dfn[maxn],id[maxn],pos[maxn],fa[maxn],a[maxn];
inline LL min(LL a,LL b) {return a<b?a:b;}
inline LL max(LL a,LL b) {return a>b?a:b;}
inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
inline mat operator*(mat a,mat b) {
mat c;
c.a[0][0]=min(a.a[0][0]+b.a[0][0],a.a[0][1]+b.a[1][0]);
c.a[0][1]=min(a.a[0][1]+b.a[1][1],a.a[0][0]+b.a[0][1]);
c.a[1][0]=min(a.a[1][0]+b.a[0][0],a.a[1][1]+b.a[1][0]);
c.a[1][1]=min(a.a[1][1]+b.a[1][1],a.a[1][0]+b.a[0][1]);
return c;
}
void dfs1(int x) {
sum[x]=1;int maxx=-1;
for(re int i=head[x];i;i=e[i].nxt) {
if(deep[e[i].v]) continue;
deep[e[i].v]=deep[x]+1;fa[e[i].v]=x;
dfs1(e[i].v);sum[x]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
}
}
int dfs2(int x,int topf) {
top[x]=topf,dfn[x]=++__,id[__]=x;
if(!son[x]) return bot[x]=x;
bot[x]=dfs2(son[x],topf);
for(re int i=head[x];i;i=e[i].nxt) {
if(top[e[i].v]) continue;
dfs2(e[i].v,e[i].v);
}
return bot[x];
}
inline void pushup(int i) {d[i]=d[i<<1]*d[i<<1|1];}
void build(int x,int y,int i) {
l[i]=x,r[i]=y;
if(x==y) {
int now=id[x];pos[now]=i;
for(re int j=head[now];j;j=e[j].nxt) {
if(deep[e[j].v]<deep[now]||e[j].v==son[now]) continue;
dp[now][1]+=min(dp[e[j].v][0],dp[e[j].v][1]);
dp[now][0]+=dp[e[j].v][1];
}
f[now][0]=dp[now][0];f[now][1]=dp[now][1];dp[now][1]+=a[now];
d[i].a[0][0]=inf,d[i].a[0][1]=dp[now][0];
d[i].a[1][0]=d[i].a[1][1]=dp[now][1];
if(son[now])
dp[now][1]+=min(dp[son[now]][0],dp[son[now]][1]),dp[now][0]+=dp[son[now]][1];
return;
}
int mid=x+y>>1;
build(mid+1,y,i<<1|1),build(x,mid,i<<1);pushup(i);
}
mat query(int x,int y,int i) {
if(x<=l[i]&&y>=r[i]) return d[i];
int mid=l[i]+r[i]>>1;
if(y<=mid) return query(x,y,i<<1);
if(x>mid) return query(x,y,i<<1|1);
return query(x,y,i<<1)*query(x,y,i<<1|1);
}
inline void updata(int i,mat val) {d[i]=val;while(i) {i>>=1;pushup(i);}}
inline void change(int x,LL val) {
mat pre=query(dfn[top[x]],dfn[bot[x]],1);
mat t;
t.a[0][0]=inf,t.a[0][1]=f[x][0],t.a[1][0]=t.a[1][1]=f[x][1]+val;
updata(pos[x],t);
while(1) {
if(top[x]==1) return;
mat now=query(dfn[top[x]],dfn[bot[x]],1);
mat t=d[pos[fa[top[x]]]];
t.a[0][1]-=pre.a[1][1];
t.a[0][1]+=now.a[1][1];
t.a[1][1]-=min(pre.a[0][1],pre.a[1][1]);
t.a[1][1]+=min(now.a[0][1],now.a[1][1]);
t.a[1][0]=t.a[1][1];
x=fa[top[x]];
pre=query(dfn[top[x]],dfn[bot[x]],1);
updata(pos[x],t);
}
}
signed main() {
n=read(),m=read();scanf("%s",opt);int x,y,A,B;
for(re int i=1;i<=n;i++) a[i]=read();
for(re int i=1;i<n;i++) {
x=read(),y=read();
if(x>y) std::swap(x,y);ma[mp(x,y)]=1;
add(x,y),add(y,x);
}
deep[1]=1,dfs1(1),dfs2(1,1),build(1,n,1);
while(m--) {
x=read(),A=read(),y=read(),B=read();
if(!A&&!B&&ma[mp(min(x,y),max(x,y))]) {puts("-1");continue;}
if(deep[x]>deep[y]) std::swap(x,y),std::swap(A,B);
if(A) change(x,-1ll*Inf+a[x]);
else change(x,Inf+a[x]);
if(B) change(y,-1ll*Inf+a[y]);
else change(y,Inf+a[y]);
mat now=query(1,dfn[bot[1]],1);
LL ans=min(now.a[0][1],now.a[1][1]);
if(A) ans+=Inf;
if(B) ans+=Inf;
printf("%lld\n",ans);
change(y,a[y]);change(x,a[x]);
}
return 0;
}

「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. NOIP2018保卫王国

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

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

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

  7. [NOIP2018]保卫王国

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

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

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

  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. Debian - 安装随记

    为什么要突然换个操作系统? 之前使用的是Lubuntu,可见硬件非常糟糕. 更糟糕的是Lubuntu被玩坏了,很多程序不能正常运行. 于是打算换Debian + XFCE. 随手记录一下遇到的一些坑, ...

  2. [javaSE] 集合工具类(Collections-sort)

    java为我们提供了一个集合的工具类,方便我们对集合进行操作,里面的方法都是静态方法. Collections.sort()方法,参数:List<T>集合对象,这个对象带着泛型,是为了保证 ...

  3. 一:Java基础

    /-- 第一章:概念 --/ 1.java特点:跨平台.面向对象.开源 2.JVM是Java虚拟机的缩写,可以实现跨平台 3.java运行原理: 1).编写java源文件,以.java作为后缀名 2) ...

  4. vmware创建centos虚拟机

    下载centos 安装之前你需要下载centos镜像:http://mirrors.aliyun.com/ 创建虚拟机 如果还没有安装vmware请参考:https://www.cnblogs.com ...

  5. 一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了

    一文看懂大数据的技术生态圈,Hadoop,hive,spark都有了 转载: 大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它 ...

  6. 【转】Eclipse,MyEclipse快捷键及字体设置

    1.如何调节Eclipse下console输出字体的大小?         打开window - preferences-- general - appearance - colors and fon ...

  7. Node.js+websocket+mongodb实现即时聊天室

    ChatRoom Node.js+websocket+mongodb实现即时聊天室 A,nodejs简介:Node.js是一个可以让javascript运行在服务器端的平台,它可以让javascrip ...

  8. Swift Development – List of Resources You Must Bookmark

    Ever since the introduction of iOS, there is iOS development fever across the globe. Many iOS develo ...

  9. Http Status Code 套餐合集(转载)

    1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态代码. 100(继续)请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101(切换协议)请求者已要 ...

  10. ajax异步上传图片三种方案

    转自:http://www.jb51.net/article/51180.htm 注:自己尝试了前两种,都可用: 目前常用的异步文件上传功能有几种,比较多见的如使用iframe框架形式,ajax功能效 ...