题目描述

Z 国有nn座城市,n - 1n−1条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达。

Z 国的国防部长小 Z 要在城市中驻扎军队。驻扎军队需要满足如下几个条件:

  • 一座城市可以驻扎一支军队,也可以不驻扎军队。
  • 由道路直接连接的两座城市中至少要有一座城市驻扎军队。
  • 在城市里驻扎军队会产生花费,在编号为i的城市中驻扎军队的花费是p_ipi​。

小 Z 很快就规划出了一种驻扎军队的方案,使总花费最小。但是国王又给小 Z 提出 了mm个要求,每个要求规定了其中两座城市是否驻扎军队。小 Z 需要针对每个要求逐一 给出回答。具体而言,如果国王提出的第jj个要求能够满足上述驻扎条件(不需要考虑 第 jj 个要求之外的其它要求),则需要给出在此要求前提下驻扎军队的最小开销。如果 国王提出的第jj个要求无法满足,则需要输出-1 (1 ≤ j ≤ m)−1(1≤j≤m)。现在请你来帮助小 Z。

输入输出格式

输入格式:

第 11 行包含两个正整数n,mn,m和一个字符串typetype,分别表示城市数、要求数和数据类型。typetype是一个由大写字母 AA,BB 或 CC 和一个数字 11,22,33 组成的字符串。它可以帮助你获得部分分。你可能不需要用到这个参数。这个参数的含义在【数据规模与约定】中 有具体的描述。

第 22 行nn个整数p_ipi​,表示编号ii的城市中驻扎军队的花费。

接下来 n - 1n−1 行,每行两个正整数u,vu,v,表示有一条uu到vv的双向道路。

接下来 mm 行,第jj行四个整数a,x,b,y(a ≠ b)a,x,b,y(a≠b),表示第jj个要求是在城市aa驻扎xx支军队, 在城市bb驻扎yy支军队。其中,xx 、 yy 的取值只有 00 或 11:若 xx 为 00,表示城市 aa 不得驻 扎军队,若 xx 为 11,表示城市 aa 必须驻扎军队;若 yy为 00,表示城市 bb不得驻扎军队, 若 yy为 11,表示城市 bb 必须驻扎军队。

输入文件中每一行相邻的两个数据之间均用一个空格分隔。

输出格式:

输出共 mm 行,每行包含 11 个整数,第jj行表示在满足国王第jj个要求时的最小开销, 如果无法满足国王的第jj个要求,则该行输出 -1−1。

输入输出样例

输入样例#1: 复制

5 3 C3
2 4 1 3 9
1 5
5 2
5 3
3 4
1 0 3 0
2 1 3 1
1 0 5 0
输出样例#1: 复制

12
7
-1

说明

【样例解释】

对于第一个要求,在 44 号和 55 号城市驻扎军队时开销最小。

对于第二个要求,在 11 号、22 号、33 号城市驻扎军队时开销最小。

第三个要求是无法满足的,因为在 11 号、55 号城市都不驻扎军队就意味着由道路直接连 接的两座城市中都没有驻扎军队。

【数据规模与约定】

对于 100\%100%的数据,n,m ≤ 100000,1 ≤ p_i ≤ 100000n,m≤100000,1≤pi​≤100000。

数据类型的含义:

AA:城市ii与城市i + 1i+1直接相连。
BB:任意城市与城市 11 的距离不超过 100100(距离定义为最短路径上边的数量),即如果这 棵树以 11 号城市为根,深度不超过 100100。
CC:在树的形态上无特殊约束。
11:询问时保证a = 1,x = 1a=1,x=1,即要求在城市 11 驻军。对b,y没有限制。
22:询问时保证a,ba,b是相邻的(由一条道路直接连通)
33:在询问上无特殊约束。

题解:

首先一般的暴力$dp[u][0] = \sum dp[v][1]$ , $dp[u][1]  = \sum min(dp[v][0],dp[v][1]) + a[u]$

复杂度$O(n^2)$

考虑倍增优化  :

fa[u][i]表示u向上跳2^i的祖先,然后用f[u][i]表示以fa[u][i]为根节点,不包括u的子树的最优dp值;

将f[u][i]写成一个2*2的矩阵,表示fa[u][i]和u是否选择;

更新一个点u,直接从u倍增到根节点就可以了;

考虑同时更新u和v,先跳到他们lca的儿子,再从lca跳到根,分类合并一下三个矩阵;

注意特判v和u有祖先关系的情况;

LCT做法:
      其实这东西似乎叫动态dp

一般套路是将转移写成矩阵然后用数据结构维护;

树链剖分后 f[u][0/1]表示u为根的子树dp值,g[u][0/1]表示u为根的子树除开重儿子($son_{u}$)的dp值;

$f[u][0] = g[u][0] + f[son_{u}][1] $  ,

$f[u][1] = g[u][1] + min( f[son_{u}][0] , f[son_{u}][1] ) $

将加法定义成取min,乘法定义成加法,转移写成矩阵:$$\\
\begin{pmatrix} f[son_{u}][0] & f[son_{u}][1] \end{pmatrix}  \
\begin{pmatrix} \infty & g[u][1] \\ g[u][0] & g[u][1] \end{pmatrix}
=
\begin{pmatrix} f[u][0] & f[u][1] \end{pmatrix}
$$

用LCT维护(只写了倍增,后面补上)

另外推荐一个动态dp的题:http://noi.ac/problem/111

 #include<bits/stdc++.h>
#define il inline
#define rg register
#define ll long long
using namespace std;
const int N=;
ll inf=1e15;
struct mat{
ll c[][];
mat(ll _a=inf,ll _b=inf,ll _c=inf,ll _d=inf){
c[][]=_a;c[][]=_b;
c[][]=_c;c[][]=_d;
}
mat operator *(const mat&A){
mat ret;
for(int i=;i<;i++)
for(int j=;j<;j++){
ret.c[i][j]=min(inf,min(c[i][]+A.c[][j],c[i][]+A.c[][j]));
}
return ret;
}
}f[N][];
char gc(){
static char*p1,*p2,s[];
if(p1==p2)p2=(p1=s)+fread(s,,,stdin);
return(p1==p2)?EOF:*p1++;
}
int rd(){
int x=; char c=gc();
while(c<''||c>'')c=gc();
while(c>=''&&c<='')x=(x<<)+(x<<)+c-'',c=gc();
return x;
}
int n,m,o,hd[N];
ll a[N],dep[N],fa[N][],bin[],dp[N][];
struct Edge{int v,nt;}E[N<<];
void adde(int u,int v){
E[o]=(Edge){v,hd[u]};hd[u]=o++;
E[o]=(Edge){u,hd[v]};hd[v]=o++;
}
void dfs0(int u,int F){
dp[u][]=;dp[u][]=a[u];
for(rg int i=hd[u];~i;i=E[i].nt){
int v=E[i].v;
if(v==F)continue;
dfs0(v,u);
dp[u][]+=dp[v][];
dp[u][]+=min(dp[v][],dp[v][]);
}
}
void dfs(int u,int F){
dep[u]=dep[fa[u][]=F]+;
f[u][]=mat(
inf,
dp[fa[u][]][]-dp[u][],
dp[fa[u][]][]-min(dp[u][],dp[u][]),
dp[fa[u][]][]-min(dp[u][],dp[u][])
);
for(rg int i=;bin[i]<dep[u];i++){
fa[u][i]=fa[fa[u][i-]][i-];
f[u][i]=f[fa[u][i-]][i-]*f[u][i-];
}
for(rg int i=hd[u];~i;i=E[i].nt){
int v=E[i].v;
if(v==F)continue;
dfs(v,u);
}
}
void solve(int u,int x,int v,int y){
if(dep[u]<dep[v])swap(u,v),swap(x,y);
mat tu,tv,t;
tu=mat(dp[u][],inf,inf,dp[u][]);
tv=mat(dp[v][],inf,inf,dp[v][]);
for(int i=;i<;i++)if(bin[i]&(dep[u]-dep[v])){
tu=f[u][i]*tu;
u=fa[u][i];
}
if(u==v){
ll ans;
t=mat(,inf,inf,);
for(int i=;i<;i++)if(bin[i]&(dep[u]-)){
t=f[u][i]*t;
u=fa[u][i];
}
ans= min(t.c[][y],t.c[][y])+tu.c[y][x];
if(ans>=inf)puts("-1");
else printf("%lld\n",ans);
return;
}
for(int i=;~i;i--)if(fa[u][i]!=fa[v][i]){
tu=f[u][i]*tu;
tv=f[v][i]*tv;
u=fa[u][i];
v=fa[v][i];
}
t=mat(
dp[fa[u][]][]-dp[u][]-dp[v][],
inf,
inf,
dp[fa[u][]][]-min(dp[u][],dp[u][])-min(dp[v][],dp[v][])
);
u=fa[u][];
for(int i=;i<;i++)if(bin[i]&(dep[u]-)){
t=f[u][i]*t;
u=fa[u][i];
}
ll ans=inf;
ans = min(
min(t.c[][],t.c[][])+tu.c[][x]+tv.c[][y],
min(t.c[][],t.c[][])+min(tu.c[][x],tu.c[][x])+min(tv.c[][y],tv.c[][y])
);
if(ans>=inf)puts("-1");
else printf("%lld\n",ans);
}
int main(){
freopen("defense.in","r",stdin);
freopen("defense.out","w",stdout);
n=rd(); m=rd(); gc(); gc();
for(rg int i=bin[]=;i<;i++)bin[i]=bin[i-]<<;
for(rg int i=;i<=n;i++)a[i]=rd(),hd[i]=-;
for(rg int i=;i<n;i++)adde(rd(),rd());
dfs0(,);
dfs(,);
for(rg int i=,u,v,x,y;i<=m;i++){
u=rd();x=rd();v=rd();y=rd();
solve(u,x,v,y);
}
return ;
}

倍增

【noip2018】【luogu5024】保卫王国的更多相关文章

  1. 「NOIP2018」保卫王国

    「NOIP2018保卫王国」 题目描述 有一棵 \(n\) 个点, 点有点权 \(a_i\),\(m\) 组询问, 每次求钦点两个节点必须选或者必须不选后的树上最小点覆盖. \(1 \leq n, m ...

  2. noip2018 d2t3 保卫王国 解题报告

    保卫王国 电脑卡懒得把题面挪过来了. 朴素 \[ dp_{i,0}=\sum dp_{s,1}\\ dp_{i,1}=\sum \min(dp_{s,0},dp_{s,1})+p_i \] 然后直接动 ...

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

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

  4. loj 2955 「NOIP2018」保卫王国 - 树链剖分 - 动态规划

    题目传送门 传送门 想抄一个短一点ddp板子.然后照着Jode抄,莫名其妙多了90行和1.3k. Code /** * loj * Problem#2955 * Accepted * Time: 26 ...

  5. @NOIP2018 - D2T3@ 保卫王国

    目录 @题目描述@ @题解@ @代码@ @题目描述@ Z 国有n座城市,n−1 条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻 ...

  6. NOIP2018 Day2T3 保卫王国

    首先不考虑强制要求的话是一个经典问题,令 \(f_{i, 0 / 1}\) 为 \(i\) 选或不选时以 \(i\) 为根的子树的最优答案.那么就有转移 \(f_{u, 0} = \sum f_{v, ...

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

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

  8. LG5024 保卫王国

    题意 题目描述 Z 国有\(n\)座城市,\(n - 1\)条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻扎军队.驻扎军队需要 ...

  9. Uoj 441 保卫王国

    Uoj 441 保卫王国 动态 \(dp\) .今天才来写这个题. 设 \(f[u][0/1]\) 表示子树 \(u\) 中不选/选 \(u\) 时的最小权值和,显然有:\(f[u][0]=\sum ...

  10. [NOIP2018TG]保卫王国

    [NOIP2018TG]保卫王国 BZOJ luogu 当动态dp模板题写的,(全集-最大点权独立集)不能放军队的+inf,必须放军队-inf即可 注意矩阵乘法的顺序问题 #define ll lon ...

随机推荐

  1. MySQL☞左外链接与右外连接

    外链接查询:即要查询有关联关系的数据,还要查询没有关联关系的数据.(个人理解为:表A和表B两个关联的列中)如下图: emmm,简单的来说两个表的关联关系:book.bid=bookshop.id,他们 ...

  2. 这才是球王应有的技艺,他就是C罗

    四年一度的世界杯在本周四拉开了帷幕,俄罗斯以5:0碾压沙特阿拉伯,让我们惊呼战斗名族的强大,其后的摩洛哥VS伊朗,摩洛哥前锋布哈杜兹将足球顶入自家球门,这......咳,咳,本来是为了解围,没想到成就 ...

  3. 如何计算FOB价格

    FOB价格是国际贸易术语常有的一种算法,针对不同的对象,FOB价格也有不一样的算法.对于做外贸生意的朋友,需要了解FOB价格以及各项费用名称,以及如何计算FOB价格. FOB价格是国际FOB价格语常有 ...

  4. ES6的新特性(20)—— Module 的加载实现

    Module 的加载实现 上一章介绍了模块的语法,本章介绍如何在浏览器和 Node 之中加载 ES6 模块,以及实际开发中经常遇到的一些问题(比如循环加载). 浏览器加载 传统方法 HTML 网页中, ...

  5. Intense Heat(前缀和或尺取)

    The heat during the last few days has been really intense. Scientists from all over the Berland stud ...

  6. PSP Daily软件Alpha版本——基于NABCD评论,及改进建议

    1.根据(不限于)NABCD评论作品的选题: 此软件的用户人群较为明确,即:用户(软件工程课上学生)记录例行报告.写每周PSP表格和统计的需求.潜在用户还有未来该课堂的学生和需要用PSP方法记录任务完 ...

  7. SpringMVC相关的面试题

    1.什么是springMVC springmvc是spirng框架的一个模块,是一个基于MVC框架的web框架 2.springmvc的流程 a.客户端发送请求 b.前端控制器DispatcherSe ...

  8. Rsyslog-legacy(旧版本语法)配置说明及举例

    1. RULES-书写规则 格式:日志设备(类型).日志级别             日志处理方式 (1)日志类型分类 auth pam产生的日志 authpriv ssh,ftp等登录信息的验证信息 ...

  9. Java多线程下单例

    /* 多线程下的单例 */ //饿汉式 class Single { private static final Single s = new Single(); private Single(){} ...

  10. 使用kdump内核调试工具遇到的问题及解决

    修改linux内核代码或者内核模块的时候,搞不好就会造成linux死机崩溃,crash死机后/var/log/kern.log里面不会有任何异常信息记录.这时候kdump就会派上用场了,网上kdump ...