此题场上打了一个正确的$44pts$,接着看错题疯狂$rush$“正确”的$44pts$,后来没$rush$完没将之前的代码$copy$回去,直接变零分了。。。。。

这一题我们显然有一种$O(nm)$的做法

令$f[u][0]$表示在以$u$为根的子树内部署军队,且$u$不部署军队的最小代价。

令$f[u][1]$表示在以$u$为根的子树内部署军队,且$u$部署军队的最小代价。

结合题意(重要!)不难推出:

$f[u][0]=\sum_{v∈son[u]} f[v][1]$

$f[u][1]=val_u+\sum_{v∈son[u]} min(f[v][0],f[v][1])}$

考虑满足能选/不能选的要求,我们只需要临时将被选择点的权值赋值为$INF$或$-INF$即可。

考虑这棵树是一条链的情况:我们用一棵线段树,每个节点维护一个答案矩阵(该区间左端点驻军/可能不驻军,该区间右端点驻军/可能不驻军时的最小代价)。我们求一个节点的答案矩阵,显然可以通过其儿子的答案矩阵,通过大力分类讨论(详见代码)实现更新。

当出现修改权值的情况时,大力改一改然后$pushup$即可。

我们考虑将这一个链上做法扩展到树上。我们用树链剖分将整棵树剖成若干条链,对于轻边上的一对节点$(u,son[u])$,我们将$son[u]$所在链的信息加入节点$u$所对应答案矩阵内即可(详见代码)。

一遍过样例开了$O2$就过了美滋滋

 #include<bits/stdc++.h>
#define mid ((a[x].l+a[x].r)>>1)
#define L long long
#define INF (1LL<<50)
#define LOW (1LL<<40)
#define M 100005
using namespace std; struct edge{int u,next;}e[M*]={}; int head[M]={},use=;
void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;} int siz[M]={},dfn[M]={},rec[M]={},top[M]={},dn[M]={},son[M]={},fa[M]={},t=; void dfs(int x){
siz[x]=;
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]){
fa[e[i].u]=x;
dfs(e[i].u);
siz[x]+=siz[e[i].u];
if(siz[son[x]]<siz[e[i].u]) son[x]=e[i].u;
}
}
void dfs(int x,int Top){
top[x]=Top; dfn[x]=++t; rec[t]=x;
if(son[x]) dfs(son[x],Top),dn[x]=dn[son[x]]; else dn[x]=x;
for(int i=head[x];i;i=e[i].next)
if(e[i].u!=fa[x]&&e[i].u!=son[x]) dfs(e[i].u,e[i].u);
} L f[M][]={},val[M]={};
void dp(int x){
f[x][]=val[x];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa[x]){
dp(e[i].u);
f[x][]+=f[e[i].u][];
f[x][]+=min(f[e[i].u][],f[e[i].u][]);
}
} struct mat{
L a[][]; mat(){memset(a,,sizeof(a));}
mat(L x){a[][]=a[][]=a[][]=a[][]=x;}
mat(L a1,L a2,L a3,L a4){a[][]=a1; a[][]=a2; a[][]=a3; a[][]=a4;}
L ans(){ return min(min(a[][],a[][]),min(a[][],a[][]));}
void upd(L now){a[][]+=now; a[][]+=now; a[][]+=now;}
friend mat operator *(mat a,mat b){
mat c=INF;
for(int i=;i<;i++)
for(int j=;j<;j++){
for(int i1=;i1<;i1++)
for(int j1=;j1<;j1++)
if(!(i1==&&j1==))
c.a[i][j]=min(c.a[i][j],a.a[i][i1]+b.a[j1][j]);
}
return c;
}
}wei[M];
struct seg{int l,r; mat s;}a[M<<];
void pushup(int x){a[x].s=a[x<<].s*a[x<<|].s;} void build(int x,int l,int r){
a[x].l=l; a[x].r=r;
if(l==r){
int u=rec[l]; L g0=,g1=val[u];
for(int i=head[u];i;i=e[i].next)
if(e[i].u!=fa[u]&&e[i].u!=son[u]){
g0+=f[e[i].u][];
g1+=min(f[e[i].u][],f[e[i].u][]);
}
a[x].s=wei[l]=mat(g1,g1,g1,g0);
return;
}
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
mat query(int x,int l,int r){
if(l<=a[x].l&&a[x].r<=r) return a[x].s;
if(r<=mid) return query(x<<,l,r);
if(mid<l) return query(x<<|,l,r);
return query(x<<,l,r)*query(x<<|,l,r);
}
mat query(int x){return query(,dfn[top[x]],dfn[dn[x]]);}
L solve(){mat hh=query(); return hh.ans();} void updata(int x,int k){
if(a[x].l==a[x].r) return void(a[x].s=wei[k]);
if(k<=mid) updata(x<<,k); else updata(x<<|,k);
pushup(x);
}
void Updata(int x,L Val){
L chg=Val-val[x]; val[x]+=chg;
wei[dfn[x]].upd(chg);
while(x){
mat last=query(x);
L lg1=last.ans(),lg0=min(last.a[][],last.a[][]); updata(,dfn[x]); mat now=query(x);
L ng1=now.ans(),ng0=min(now.a[][],now.a[][]); x=fa[top[x]]; if(!x) return;
wei[dfn[x]].upd(ng1-lg1);
wei[dfn[x]].a[][]+=ng0-lg0;
}
} int n,m; char op[]; int main(){
//freopen("defense.in","r",stdin);
//freopen("defense.out","w",stdout);
scanf("%d%d%s",&n,&m,op);
for(int i=;i<=n;i++) scanf("%lld",val+i);
for(int i=,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs();
dfs(,);
dp();
build(,,n);
//cout<<solve()<<endl;
while(m--){
int A,x,B,y; scanf("%d%d%d%d",&A,&x,&B,&y);
L lastA=val[A],lastB=val[B],chg=; if(x==) Updata(A,INF);
else Updata(A,-INF); if(y==) Updata(B,INF);
else Updata(B,-INF); L res=solve();
if(x) res+=INF+lastA;
if(y) res+=INF+lastB; Updata(A,lastA);
Updata(B,lastB); if(res>LOW){printf("-1\n"); continue;}
printf("%lld\n",res);
}
}

【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. luoguP5024 保卫王国 动态dp

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

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

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

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

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

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

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

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

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

  9. NOIP2018保卫王国

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

随机推荐

  1. HTTP 500.21 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”

    问题:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler” IIS7下部署网站出现错误,原因是先安装的II ...

  2. 创建template模板

    创建一个自己常用的快捷键的模板. 1.选择window-->preferrence--搜索temp--java 2.点击new 3.根据自己的习惯起一个名字 4.比如syso 5.语法不会,就找 ...

  3. 软件工程网络15个人作业4(201521123010徐璐琳)——alpha阶段个人总结

    一.个人总结 1. 总结自己的alpha 过程: 经过了两周的ALPHA阶段,在这之中学习到了很多,因为最开始其实是有抱着一种应付的.将就着的心理去做这个小程序,但是在完成项目的过程中,有老师和助教一 ...

  4. SSH中设置字符编码防止乱码

    1.在web.xml中加入一个过滤器和过滤范围的配置 <filter><filter-name>encoding</filter-name><filter-c ...

  5. Oracle EBS 常用网站列表

    http://www.lifandong.com/erp/356 Oracle EBS 常用网站列表 英文站: Oracle EBS R12 官方参考手册(User Guide, Implementa ...

  6. 在TFS中使用Git Tags(标签或标记),实现代码的版本管理

    一.概述: 与TFVC中标记(Label)一样,Git的标签(Tag)也是TFS系统的代码管理中非常重要的一个版本管理工具.使用标签,我们可以每个时间点的代码注上一个通俗.并且容易记忆的名称(例如标签 ...

  7. Transaction And Lock--使用资源锁来控制并发

    写过程序的朋友都知道,在多线程处理时,对于非线程安全的对象,需用使用锁定特定对象(LOCK)的方法来保证串行操作.曾经有位开发询问我,在SQL Server内部是否有类似的实现方法来控制某一操作不能并 ...

  8. js框操作-----Selenium快速入门(八)

    js框,就是JavaScript中的警告框(alert),确认框(confirm),提示框(prompt),他们都是模态窗口.什么是模态窗口,大家可以自行百度一下,简单说就是弹出的窗口是在最顶端的,你 ...

  9. RabbitMQ之消息持久化(转)

    原文地址 https://blog.csdn.net/u013256816/article/details/60875666/ 消息的可靠性是RabbitMQ的一大特色,那么RabbitMQ是如何保证 ...

  10. CSS2.1SPEC:视觉格式化模型之包含块

    原汁原味的才是最有味道的,在阅读CSS标准时对这一点的体会更加深刻了,阅读文档后的一大感觉就是很多看上去理所应当的样式表现也都有了对应的支持机制.本文首先从包含块写起,一方面总结标准中相应的阐述,并且 ...