BZOJ 5466: [Noip2018]保卫王国 动态DP
Code:
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define ll long long
#define lson (now<<1)
#define rson ((now<<1)|1)
#define setIO(s) freopen(s".in","r",stdin)
#define maxn 300000
const long long inf = 100000000000000;
using namespace std;
char uuu[9];
ll V[maxn];
int fa[maxn],hd[maxn],to[maxn],nex[maxn],siz[maxn],hson[maxn];
int F[maxn][2];
int top[maxn],bot[maxn],dfn[maxn],ln[maxn];
int edges,tim,n,Q;
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
struct Matrix
{
ll a[2][2];
ll*operator[](int x){return a[x]; }
}t[maxn<<1],tmp[maxn];
Matrix operator*(Matrix a,Matrix b)
{
Matrix c;
c[0][0]=min(a[0][0]+b[0][0],a[0][1]+b[1][0]);
c[0][1]=min(a[0][0]+b[0][1],a[0][1]+b[1][1]);
c[1][0]=min(a[1][0]+b[0][0],a[1][1]+b[1][0]);
c[1][1]=min(a[1][0]+b[0][1],a[1][1]+b[1][1]);
return c;
}
void dfs1(int u,int ff)
{
fa[u]=ff,siz[u]=1;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[hson[u]]) hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp,ln[++tim]=u,dfn[u]=tim;
if(hson[u])
dfs2(hson[u],tp),bot[u]=bot[hson[u]];
else
bot[u]=u;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==fa[u]||v==hson[u]) continue;
dfs2(v,v);
}
}
void dfs(int u)
{
F[u][0]=0,F[u][1]=V[u];
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==fa[u]) continue;
dfs(v);
F[u][0]+=F[v][1];
F[u][1]+=min(F[v][0],F[v][1]);
}
}
void build(int l,int r,int now)
{
if(l>r) return;
if(l==r)
{
int u=ln[l];
ll f0=0,f1=V[u];
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==fa[u]||v==hson[u]) continue;
f0+=F[v][1];
f1+=min(F[v][0],F[v][1]);
}
t[now]=tmp[l]=(Matrix){inf, f0,f1,f1};
return;
}
int mid=(l+r)>>1;
build(l,mid,lson),build(mid+1,r,rson);
t[now]=t[lson]*t[rson];
}
void modify(int l,int r,int now,int p)
{
if(l==r)
{
t[now]=tmp[l];
return;
}
int mid=(l+r)>>1;
if(p<=mid)
modify(l,mid,lson,p);
else
modify(mid+1,r,rson,p);
t[now]=t[lson]*t[rson];
}
Matrix query(int l,int r,int now,int L,int R)
{
if(l==L&&r==R) return t[now];
int mid=(l+r)>>1;
if(R<=mid) return query(l,mid,lson,L,R);
if(L>mid) return query(mid+1,r,rson,L,R);
return query(l,mid,lson,L,mid)*query(mid+1,r,rson,mid+1,R);
}
void Update(int u,ll w)
{
tmp[dfn[u]][1][0]=tmp[dfn[u]][1][1]+=w-V[u], V[u]=w;
while(u)
{
Matrix a=query(1,n,1,dfn[top[u]],dfn[bot[u]]);
modify(1,n,1,dfn[u]);
Matrix b=query(1,n,1,dfn[top[u]],dfn[bot[u]]);
u=fa[top[u]];
if(!u) return;
int x=dfn[u];
ll f0=a[0][1],f1=a[1][1],g0=b[0][1],g1=b[1][1];
tmp[x][1][0]=tmp[x][1][1]=tmp[x][1][0]+min(g1,g0)-min(f1,f0);
tmp[x][0][1]=tmp[x][0][1]+g1-f1;
}
}
void solve(int a,int x,int b,int y)
{
if(!x&&!y&&(fa[a]==b||fa[b]==a)) { printf("-1\n"); return ;}
ll o=V[a],oo=V[b];
Update(a,x?o-inf:o+inf), Update(b,y?oo-inf:oo+inf);
Matrix ans=query(1,n,1,dfn[top[1]],dfn[bot[1]]);
ll h=min(ans[0][1],ans[1][1]);
if(x) h+=inf;
if(y) h+=inf;
printf("%lld\n",h);
Update(a,o), Update(b,oo);
}
int main()
{
// setIO("input");
scanf("%d%d%s",&n,&Q,uuu);
for(int i=1;i<=n;++i) scanf("%lld",&V[i]);
for(int i=1,u,v;i<n;++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
dfs1(1,0),dfs2(1,1),dfs(1),build(1,n,1);
while(Q--)
{
int a,x,b,y;
scanf("%d%d%d%d",&a,&x,&b,&y);
solve(a,x,b,y);
}
return 0;
}
BZOJ 5466: [Noip2018]保卫王国 动态DP的更多相关文章
- luogu5024 [NOIp2018]保卫王国 (动态dp)
可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵 #include<bits/stdc++.h> #define CLR(a,x) memset(a ...
- JZOJ5966. [NOIP2018TGD2T3] 保卫王国 (动态DP做法)
题目大意 这还不是人尽皆知? 有一棵树, 每个节点放军队的代价是\(a_i\), 一条边连接的两个点至少有一个要放军队, 还有\(q\)次询问, 每次规定其中的两个一定需要/不可放置军队, 问这样修改 ...
- 【NOIP2018】保卫王国 动态dp
此题场上打了一个正确的$44pts$,接着看错题疯狂$rush$“正确”的$44pts$,后来没$rush$完没将之前的代码$copy$回去,直接变零分了..... 这一题我们显然有一种$O(nm)$ ...
- luoguP5024 保卫王国 动态dp
题目大意: emmmmm 题解: QAQ #include <cstdio> #include <cstring> #include <iostream> usin ...
- LuoguP5024 保卫王国(动态DP,LCT)
最小权覆盖集 = 全集 - 最大权独立集 强制取点.不取点可以使用把权值改成正无穷或负无穷实现 接下来就是经典的"动态最大权独立集"了 O(nlogn). 这不是我说的,是immo ...
- P5024 保卫王国(动态dp/整体dp/倍增dp)
做法(倍增) 最好写的一种 以下0为不选,1为选 \(f_{i,0/1}\)为\(i\)子树的最小值,\(g_{i,0/1}\)为除i子树外的最小值 \(fh_{i,j,0/1,0/1}\)为确定\( ...
- 竞赛题解 - NOIP2018 保卫王国
\(\mathcal{NOIP2018}\) 保卫王国 - 竞赛题解 按某一个炒鸡dalao名曰 taotao 的话说: \(\ \ \ \ \ \ \ \ \ "一道sb倍增题" ...
- [NOIP2018]保卫王国(树形dp+倍增)
我的倍增解法吊打动态 \(dp\) 全局平衡二叉树没学过 先讲 \(NOIP\) 范围内的倍增解法. 我们先考虑只有一个点取/不取怎么做. \(f[x][0/1]\) 表示取/不取 \(x\) 后,\ ...
- NOIP2018保卫王国
题目大意:给一颗有点权的树,每次规定两个点选还是不选,求这棵树的最小权点覆盖. 题解 ZZ码农题. 要用动态dp做,这题就是板子,然鹅并不会,留坑代填. 因为没有修改,所以可以静态倍增. 我们先做一遍 ...
随机推荐
- BZOJ——T 1801: [Ahoi2009]chess 中国象棋
http://www.lydsy.com/JudgeOnline/problem.php?id=1801 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: ...
- django 和 mysql的一次troubleshooting
下面是一次用django连接mysql的经历,记录下来也许以后会有帮助. 首先是用django的./manage.py syncdb 去连接mysql -bash-3.2$ ./manage.py s ...
- SharePoint 2013:解决添加域名后每次都需要登录的问题
在SharePoint 2013中,当我们添加一个域名给SP后(添加域名的方法请参考此文:http://www.cnblogs.com/jianyus/archive/2013/08/10/32494 ...
- HDU 5434
其实是一道状态DP题.都是行与行之间的转移,可以知道,当某j列中有一个象,如果存在情况i-1行j-1列有象而i,j-1位置无象则不可放,或者i-1,j+1有而i,j+1无同样不可放. 使用快速状态转移 ...
- Android - Error: "java.io.IOException: setDataSource failed.: status=0x80000000"
Error: "java.io.IOException: setDataSource failed.: status=0x80000000" 本文地址: http://blog.c ...
- vim copy termi
用vim写代码时,经常遇到这样的场景,复制多行,然后粘贴. 这样做:1. 将光标移动到要复制的文本开始的地方,按v进入可视模式.2. 将光标移动到要复制的文本的结束的地方,按y复制.此时vim会自动将 ...
- RTP协议分析和详解
一.RTP协议分析 第1章. RTP概述 1.1. RTP是什么 RTP全名是Real-time Transport Protocol(实时传输协议).它是IETF提出的一个标准,对应的RF ...
- PCB 奥宝LDI 输出自动改周期检测内容
继续完善奥宝LDI输出,在自动更新周期发现前期梳理不过完善或出些从未考虑到的工艺问题, 今天将更改线路周期检测内容整理如下
- Java多线程技术-Volatile关键字解析
分析volatile关键字可以从这三个方面分析,什么是程序的原子性,什么是程序的可见性,什么是程序的有序性 什么是程序的原子性 以下语句那些是原子操作? public class ThreadCoun ...
- 【CodeForces688A】Opponents
[思路分析] 比较水的模拟题 具体见代码吧 #include<iostream> #include<cstdio> #include<algorithm> usin ...