题目大意:给定一棵树,边上有边权,m次询问,每次选定一些关键点,求将1号节点与所有关键点都切断所需的最小花销

关键点的总数<=50W

首先我们考虑暴力想法

令f[x]表示切断以x为根的子树中所有关键点的最小花销

g[x]表示x是不是关键点

那么对于x的每个子节点y有f[x]=Σmin(g[y]?INF:f[y],Distance(x,y) )

这样每次暴力做一遍树形DP,时间复杂度是O(n*m)的

现在由于每次询问的点数不一定会达到n的级别,对所有节点进行DFS非常浪费

我们可以将询问的关键点拿出来,单独模拟一次DFS

维护一个栈,栈中的元素形成一条由根节点出发的链,初始栈中只有根节点

将所有关键点按照DFS序排序

每次加入一个节点,求出节点与栈顶的LCA,将栈中所有深度大于LCA的节点全都弹掉

然后将LCA和该节点入栈,注意有些重复的情况要考虑

在这个模拟的DFS过程中顺便把DP做了即可

记得开long long

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 250100
#define INF 0x3f3f3f3fll
using namespace std;
struct abcd{int to,f,next;
}table[M<<1];
int head[M],tot;
int m,n,a[M];
int pos[M],dpt[M],fa[M][20],dis[M][20];
void Add(int x,int y,int z)
{table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;
}
void DFS(int x)
{static int cnt=0;int i;pos[x]=++cnt;dpt[x]=dpt[fa[x][0]]+1;for(i=head[x];i;i=table[i].next)if(table[i].to!=fa[x][0]){fa[table[i].to][0]=x;dis[table[i].to][0]=table[i].f;DFS(table[i].to);}
}
bool Compare(int x,int y)
{return pos[x] < pos[y];
}
int LCA(int x,int y)
{int j;if(dpt[x]<dpt[y])swap(x,y);for(j=19;~j;j--)if(dpt[fa[x][j]]>=dpt[y])x=fa[x][j];if(x==y) return x;for(j=19;~j;j--)if(fa[x][j]!=fa[y][j])x=fa[x][j],y=fa[y][j];return fa[x][0];
}
int Distance(int x,int y)
{int j,re=0x3f3f3f3f;for(j=19;~j;j--)if(dpt[fa[x][j]]>=dpt[y])re=min(re,dis[x][j]),x=fa[x][j];return re;
}
int main()
{int i,j,k,x,y,z;cin>>n;for(i=1;i<n;i++){scanf("%d%d%d",&x,&y,&z);Add(x,y,z);Add(y,x,z);}DFS(1);for(j=1;j<=19;j++)for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1],dis[i][j]=min(dis[fa[i][j-1]][j-1],dis[i][j-1]);static int g[M],stack[M],top;static long long f[M];cin>>m;for(i=1;i<=m;i++){scanf("%d",&k);for(j=1;j<=k;j++)scanf("%d",&a[j]);sort(a+1,a+k+1,Compare);stack[++top]=1;f[1]=0;g[1]=0;for(j=1;j<=k;j++){int lca=LCA(stack[top],a[j]);while(dpt[stack[top]]>dpt[lca]){if(dpt[stack[top-1]]<=dpt[lca]){int temp=min(g[top]?INF:f[top],(long long)Distance(stack[top],lca) );stack[top--]=0;if(lca!=stack[top]){stack[++top]=lca;f[top]=0;g[top]=0;}f[top]+=temp;break;}else{f[top-1]+=min(g[top]?INF:f[top],(long long)Distance(stack[top],stack[top-1]) );stack[top--]=0;}}if(stack[top]!=a[j]){stack[++top]=a[j];f[top]=0;}g[top]=1;}while(top>1){f[top-1]+=min(g[top]?INF:f[top],(long long)Distance(stack[top],stack[top-1]) );stack[top--]=0;}printf("%lld\n",f[top--]);}return 0;
}
/*
f[x]表示切断以x为根的子树中所有关键点的最小花销
g[x]表示x是不是关键点
f[x]=Σmin(g[table[i].to]?INF:f[table[i].to],Distance(x,table[i].to) )
*/

BZOJ 2286 SDOI2011 消耗战 倍增LCA+单调栈相关推荐

  1. 【bzoj3879】SvT 后缀数组+倍增RMQ+单调栈

    题目描述 (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干个后缀(以其在S中出现的起始位置来表示), ...

  2. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2326  Solved: 1054 [Submit][Stat ...

  3. bzoj 4237: 稻草人(CDQ分治+单调栈+二分)

    4237: 稻草人 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1352  Solved: 594 [Submit][Status][Discus ...

  4. BZOJ 1787 AHOI2008 紧急集合 倍增LCA

    题目大意:给定一棵树,多次询问到三个点距离之和最小的点和距离 首先易知到两个点距离之和最小的点一定在两点间的路径上 于是到三个点距离之和最小的点一定在两两之间路径的交点上 然后很容易就会知道这个交点一 ...

  5. bzoj2286 [Sdoi2011]消耗战 单调栈+lca

    这个题意思非常明确,就是删除尽量小的边使1和指定点不连通 对于一次询问,dfs一遍即可,但需要log级别的 然后条件里有个Σ,显然复杂度和他有关,对每个点都需要一个均摊log的 然后有两个基本思路, ...

  6. Power OJ 2854 小Z的糖果难题 【单调栈+倍增】

    传送门 中文题目就不在阐述题意 比赛时我们用分块来解决的,但是T掉了... 思路:我们使用单调栈维护的每个点可以跳跃到的下一个点,相当于两个点之间可以建一条边(如果不存在下一个点,可以和一个虚拟根结点 ...

  7. BZOJ 2144 跳跳棋(神仙建模题,倍增 LCA,二分)【BZOJ修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2144 是 hydro 的 BZOJ ...

  8. [BZOJ 3238] [AHOI 2013] 差异 【后缀数组 + 单调栈】

    题目链接:BZOJ - 3238 题目分析 显然,这道题就是求任意两个后缀之间的LCP的和,这与后缀数组的联系十分明显. 求出后缀数组后,求出字典序相邻两个后缀的LCP,即 Height 数组. 那么 ...

  9. [2020多校A层12.1]树(倍增/单调栈/dfs栈)

    [2020多校A层12.1]树 求解树上从u到v的最长贪心上升序列,也就是只要有比它大的就选择它,可以发现这个问题性质,就是每个点对应了唯一的一个第一个比它大的点,那么我们可以向它们之间连边,然后问题 ...

  10. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问, 每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接. 最少的边权和是多少. (n<=250000,sigma(ki)&l ...

最新文章

  1. php 保存 json,保存PHP中的Array,是用JSON, serialize还是var_export?
  2. 被同事嘲笑说技术方案没深度?
  3. 数据包提取文件_航测怎样高效提取无人机POS航点数据
  4. 在线阅读试听视频小程序模板源码
  5. CSS经验分享:如何书写可维护的CSS代码01
  6. Extjs TreeNode的图标元素。 (节点图标, expand的加减号)
  7. (译)iOS Code Signing: 解惑
  8. Vue后台管理通用模板
  9. 改纸盒大小_包装纸箱改大小
  10. Kotlin是如何帮助你避免内存泄漏的?
  11. 安卓源码目录最全解析
  12. mysql 并发 链接失败_瞬发大量并发连接 造成MySQL连接不响应的分析
  13. win7用计算机名无法访问局域网,Win7系统在局域网内无法访问文件内容的解决方法...
  14. cc链2(小宇特详解)
  15. DedeCMS织梦教程:菜鸟级基础问题解决方法大汇总
  16. 手机通讯录被删除后怎么恢复
  17. 硅谷如何看待阿里巴巴?
  18. java处理1927 12 31_为什么减去这两次(在1927年)给出一个奇怪的结果?
  19. VGG——CNN经典网络模型(pytorch实现)
  20. Qt5 bug error c2001: 常量中有换行符

热门文章

  1. Android反射系统截图Api
  2. 技术不牛如何才拿到国内IT巨头的Offer
  3. AAC MP3音频帧采样点大小
  4. 登录服务器时显示 IE COOKIE阻止,[IE问题]IE相关设置-智明协同
  5. 一文搞定卷积神经网络——从原理到应用
  6. Android+Opencv图形的形状颜色识别
  7. H.264中CBR VBR FIXQP
  8. 取消全部呼叫转移代码_不想接电话,又不好意思挂断?输入一串代码,让你手机秒变空号!...
  9. “MATLAB拒绝访问”问题的解决方法
  10. Linux知识点总结(思维导图,建议收藏)