CF526G Spiders Evil Plan(树上最优性问题、倍增+线段树)

Description

一棵 n 个结点的树,有正边权。
用 y 条链覆盖这棵树,满足:

  • 所有链连通(有重点即算作相连)
  • 点 x 被覆盖
  • 被覆盖的边的权值和尽可能大
    q 次给出 x, y,询问最大边权和,强制在线。
    n, q ≤ 10510^5105

Solution

  • 可以发现一些比较显然的性质:
  1. 权值是正的,那么链的端点一定可以全部调整成叶子。
  2. 如果链不连通,可以交换链的端点使它们连通。
  3. 使用 k 条路径就可以覆盖一棵有 2k 个叶子的树。(先以任意方式匹配叶子。如果有两条路径不相交,可以调整成相交的情况。
    不断调整就可以让任意两条路径都相交,于是显然覆盖了整棵树。)
  • 现在问题是寻找 2 ∗ y 个叶子,使 x 被包含,使被包含的边权和最大。
  • 考虑单次询问怎么办。如果只有一次询问,我们就把询问的点 x 提作根,如果 x 的度数不为 1 ,那么选 y 条路径的最优方案必然可以转化为选 2y 个叶子,然后求这 2y 个叶子到 x 的路径的并的长度。如果 x 的度数为 1 的话,那么就是选 2y-1 个叶子,因为有一条路径要从 x 出发。
  • 那么显然就可以贪心的选当前贡献最大的叶子加入答案了。
  • 如果有多组询问呢?每次询问都换根显然不现实,但发现每次询问中,一定存在一种方案使得直径的两端中至少有一端被选取。
  • 那我们就可以把直径的两个端点分别作为根来考虑,最后询问的时候取最大值即可。
  • 考虑对每棵树预处理出 ansians_iansi 表示当前选了 i 个叶子的最大权值和,这个可以用 DFS序的线段树或者是长链剖分来实现。
  1. 线段树实现:每个叶子节点的贡献是 它的深度-它到根路径上已经被其它路径覆盖的部分的长度,用线段树维护一下叶子的贡献,每次贪心的选取贡献最大的叶子
  2. 长链剖分实现:一个子树内,最先被选的显然是深度最大的叶子,那么一个叶子的贡献,就是在长链剖分后,所在重链以及上方第一条轻边的距离。
  • 然后考虑一次询问 x,y。如果 ans2y−1ans_{2y-1}ans2y1中包含了 x 点,那么直接输出 ans2y−1ans_{2y-1}ans2y1即可。否则,加入 x 子树内最深叶子,然后需要删去一个之前选的叶子,使得减少的权值最小:
  1. 这个叶子可能是最后一个被选的叶子,也就是贡献最小的那个。
  2. 由于 x 的加入,与 x 的 lca 最深的被选叶子的贡献可能会减小,而被删去。(找离 x 最近的有叶子被选的祖先的一条路径,砍掉一半后跟 x 的子树中深度最大的点接上。)
  • 可以发现,第一种情况好办,倍增跳到到第一个被访问时间 ≤2y−2\leq 2y-22y2 祖先 u ,那么答案就是 ans2y−2−dep[u]+mx[x]ans_{2y-2}-dep[u]+mx[x]ans2y2dep[u]+mx[x]
  • 然后考虑第二种情况。第二种情况乍一看需要维护在所有时间所有点的子树内选的叶子节点的权值的最小值,这个很麻烦。但是仔细想想可以发现,只有在这个祖先的子树内只有一个叶子节点被选的时候,这种情况才可能有第一种情况优。因为如果多于两个叶子,那么删掉最小的那个叶子节点所减去的依旧是这个点加进来时候的权值,既然是减去加进来的权值那么第一种情况显然是最小的。如果只有一个叶子,那么这个叶子所代表的链跟 x 到根的路径是有交的,所以才有可能更短。实现方面可以倍增跳到第一个被访问时间 ≤2y−1\leq 2y-12y1的节点 u,那么答案就会是 ans2y−1−mx[u]+mx[x]ans_{2y-1}-mx[u]+mx[x]ans2y1mx[u]+mx[x]
  • 那么最终的答案就是两颗树的两种情况的最大值了。
  • 时间复杂度 O((n+q)log⁡n)O((n+q)\log n)O((n+q)logn)
    疑问:就网上的其它博客和我自己的提交来看,直径两端点分别作为根的情况好像不用都考虑,随便找一种就好。这样做为什么是对的?知道的朋友可以麻烦解答一下吗?

Code

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e5+5;
struct Edge{int v,w,nxt;
}edge[N<<1];
int n,m,head[N],cnt,rt,mxd,lstans,ans[N];
int fa[N][25],dep[N],son[N],dfn[N],ind,ln[N],md[N],low[N];
pair<int,int> mx[N<<2];int tag[N<<2];
int vis[N];
void add(int u,int v,int w){edge[++cnt].v=v;edge[cnt].w=w;edge[cnt].nxt=head[u];head[u]=cnt;
}
void find(int u,int f,int d){if(d>mxd){rt=u;mxd=d;} for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==f) continue;find(v,u,d+edge[i].w);}
}
void dfs(int u,int f){ln[dfn[u]=++ind]=u;md[u]=dep[u];for(int i=1;i<=20;i++){if(!fa[fa[u][i-1]][i-1]) break;fa[u][i]=fa[fa[u][i-1]][i-1];}for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(v==f) continue;dep[v]=dep[u]+edge[i].w;fa[v][0]=u;dfs(v,u);md[u]=max(md[u],md[v]);}low[u]=ind;
}
void pushup(int u){if(mx[u<<1].first<mx[u<<1|1].first) mx[u]=mx[u<<1|1];else mx[u]=mx[u<<1];
}
void build(int u,int l,int r){if(l==r){mx[u]=make_pair(dep[ln[l]],ln[l]);return;}int mid=(l+r)>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void pushdown(int u,int l,int r){if(tag[u]){mx[u<<1].first+=tag[u];mx[u<<1|1].first+=tag[u];tag[u<<1]+=tag[u];tag[u<<1|1]+=tag[u];tag[u]=0;}
}
void update(int u,int l,int r,int a,int b,int w){if(a<=l&&r<=b){mx[u].first+=w;tag[u]+=w;return;}pushdown(u,l,r);int mid=(l+r)>>1;if(a<=mid) update(u<<1,l,mid,a,b,w);if(b>mid) update(u<<1|1,mid+1,r,a,b,w);pushup(u);
}
void prework(){dfs(rt,0);build(1,1,n);//贪心:每次选取贡献最大的点,选完后修改其它点的贡献 for(int i=2;i<=n;i++){ans[i]=ans[i-1]+mx[1].first;for(int j=mx[1].second;j&&!vis[j];j=fa[j][0]){vis[j]=i;update(1,1,n,dfn[j],low[j],dep[fa[j][0]]-dep[j]);}}
}
int solve(int x,int y){y=min(y,n);if(vis[x]<=y) return ans[y];//x已经被覆盖int u=x;for(int i=20;i>=0;i--)if(vis[fa[x][i]]>y) x=fa[x][i];x=fa[x][0];return ans[y]+md[u]-dep[x]-min(dep[x],min(ans[y]-ans[y-1],md[x]-dep[x]));
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);}find(1,0,0);//找直径端点 prework();for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);u=(u+lstans-1)%n+1;v=(v+lstans-1)%n+1;printf("%d\n",lstans=solve(u,v<<1));}return 0;
}

参考文章:
https://www.luogu.com.cn/blog/46396/solution-cf526g

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/320242.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CAP带你轻松玩转ASP.NETCore消息队列

CAP是什么&#xff1f;CAP是由我们园子里的杨晓东大神开发出来的一套分布式事务的决绝方案&#xff0c;是.Net Core Community中的第一个千星项目&#xff08;目前已经1656 Start&#xff09;&#xff0c;具有轻量级、易使用、高性能等特点。https://github.com/dotnetcore/CAP…

装备合成

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 输入描述: 输入包含t组数据 第一行一个整数t 接下来t行每行两个整数x,y 输出描述: 每组数据输出一行一个…

P4161-[SCOI2009]游戏【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P4161 题目大意 一个1∼n1\sim n1∼n的排列&#xff0c;f(x)f(x)f(x)表示在置换xxx下置换多少次才能回到原来的排列&#xff0c;求在所有置换下f(x)f(x)f(x)的所有可能的值的数量。 解题思路 一个置换的fff值就是这个置换的…

【spfa】假期计划(jzoj 3936)

假期计划 jzoj 3936 题目大意 给你一个有向图&#xff08;n,m⩽20000n,m\leqslant 20000n,m⩽20000&#xff09;&#xff0c;现在有一些作为枢纽的点&#xff0c;且保证每一条边的两个点至少有一个是枢纽点&#xff0c;现在给q个询问&#xff0c;问某一个点到另一个点的最短…

CF650E Clockwork Bomb(树上构造类问题、并查集)

Description 给出两棵 n 结点的有标号树。 每次操作删去第一棵树的一条边&#xff0c;再加上一条边&#xff0c;需要保证此时还是一棵树。 构造一种操作序列&#xff0c;将第一棵树变成第二棵树&#xff0c;使得操作数最小。 n ≤ 51055 \times 10^55105 Solution 显然&…

微软必应从.NET Core 2.1获得了性能提升

据微软工程师Mukul Sabharwal介绍&#xff0c;在将微软搜索引擎必应迁移到.NET Core 2.1之后&#xff0c;内部服务延迟降低了34%&#xff0c;这主要归功于.NET社区贡献的改进。按照Sabharwal的说法&#xff0c;.NET Core的多项改进贡献了大部分的性能提升&#xff0c;包括字符串…

阶乘

链接&#xff1a; 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 给定一个正整数 p 求一个最小的正整数 n&#xff0c;使得 n! 是 p 的倍数 输入描述: 第一行输入一个正整数…

P2151-[SDOI2009]HH去散步【矩阵乘法】

正题 题目链接:https://www.luogu.com.cn/problem/P2151 题目大意 nnn个点mmm条边的一张无向图&#xff0c;走过一条边后下一次就不能再走这条&#xff0c;求AAA到BBB之间有多少长度为ttt的路径。 解题思路 因为有不能再走同一条的限制&#xff0c;所以不能直接裸上矩乘&…

IQ测试(jzoj 5048)

IQ测试 jzoj 5048 题目大意 给出一个序列a&#xff0c;然后有m个询问&#xff0c;每个询问给出一个序列&#xff0c;问这个序列是否可以由序列a删掉一些数得到的 输入样例 7 1 5 4 5 7 8 6 4 5 1 5 5 8 6 3 2 2 2 3 5 7 8 4 1 5 7 4输出样例 TAK NIE TAK NIE数据范围 对…

CF1088F Ehab and a weird weight formula(树上最优性问题、贪心+倍增)

Description 给出一棵 n 个结点的树&#xff0c;点 i 有正权值 wiw_iwi​&#xff0c;wiw_iwi​ 互不相同。 除了权值最小的点&#xff0c;保证每个点 u 都有一个邻点 v 使得 wvw_vwv​ < wuw_uwu​。 构造一棵树&#xff0c;最小化代价&#xff1a; 对于每个点 u&#xf…

搭建基于云端的中间层以支持跨平台的智能视觉服务

不断演进的应用场景初级应用场景—宅在家里场景&#xff1a;Bob同学有一天在网上看到了一张建筑物的图片&#xff0c;大发感慨&#xff1a;"好漂亮啊&#xff01;这是哪里&#xff1f;我要去亲眼看看&#xff01;"Bob同学不想问别人&#xff0c;可笑的自尊心让他觉得…

YbtOJ#20235-[冲刺NOIP2020模拟赛Day9]公共序列【dp】

正题 题目链接:https://www.ybtoj.com.cn/contest/66/problem/3 题目大意 给出两个字符串A,BA,BA,B&#xff0c;求它们的最长公共子序列。 解题思路 先考虑朴素的dpdpdp&#xff0c;设fi,jf_{i,j}fi,j​表示到AAA的第iii个&#xff0c;BBB的第jjj个时候的最长公共子序列长度…

牛客算法周周练4 题解

比赛链接 文章目录A [SDOI2016]齿轮B Rinne Loves XorC 阶乘D 小石的签到题E 装备合成A [SDOI2016]齿轮 B Rinne Loves Xor C 阶乘 两个方法 题解 D 小石的签到题 题解 E 装备合成 两个方法 题解

纪中B组模拟赛总结(2020.2.22)

成绩 rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3333lyflyflyf160160160100100100101010505050 总结 T1想到DP&#xff0c;但一开始想到的方法会TLE&#xff0c;后来想到可以减去一层&#xff0c;就A了 T2瞎想了一波&#xff0c;打了一个类似于FloyedFloyedFl…

高等数学超入门学习笔记

极限 百度百科 1.数列极限 百度百科 1.1 数列 1.2 数列极限 1.3 单调收敛原理 {xn}\{x_n\}{xn​}单调递增且{xn}\{x_n\}{xn​}有上界&#xff08;可以找到实数M使{xn}\{x_n\}{xn​}中任意一项小于M&#xff09;&#xff0c;{xn}\{x_n\}{xn​}收敛&#xff08;存在象限a&…

Microsoft宣布正式发布Linux on ASE

Microsoft宣布正式发布&#xff08;GA&#xff09;用于ASE&#xff08;应用服务环境&#xff0c;App Service Environment&#xff09;的Linux。该服务使客户可结合使用Linux上的应用服务&#xff08;App Service&#xff09;特性与ASE。在正式发布版之前&#xff0c;Microsoft…

YbtOJ#20236-[冲刺NOIP2020模拟赛Day9]红点蓝点【线段树,堆】

正题 题目链接:https://www.ybtoj.com.cn/contest/66/problem/4 题目大意 平面上nnn个红点&#xff0c;nnn个蓝点&#xff0c;对于没一个红点求一个与它纵坐标距离不超过ddd的一个点与它的曼哈顿距离最短。 解题思路 一个点分为两种情况&#xff0c;在询问点左边的红点要求横…

Rinne Loves Xor

链接&#xff1a; 来源&#xff1a;牛客网 时间限制&#xff1a;C/C 2秒&#xff0c;其他语言4秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO Format: %lld题目描述 输入描述: 第一行一个整数 N&#xff0c;表示数组 A 和 B 的长度。 第二行 N …

小麦亩产一千八(jzoj 3461)

小麦亩产一千八 jzoj 3461 题目大意 给你一个正整数序列&#xff1a;a0,a1,a2a_0,a_1,a_2a0​,a1​,a2​…… a0a_0a0​为1 a1a_1a1​为p axax−1ax−2(x>1)a_xa_{x-1} a_{x-2}(x>1)ax​ax−1​ax−2​(x>1) 现在给你三个数x&#xff0c;ax&#xff0c;yx&#xf…

Pipelines - .NET中的新IO API指引(一)

原文&#xff1a;https://blog.marcgravell.com/2018/07/pipe-dreams-part-1.html作者&#xff1a;marcgravell大约两年前&#xff0c;我发表了一篇关于.NET中即将到来的体验性新IO API的博文——在那时它被叫做"Channels"&#xff1b;在2018年的五月末&#xff0c;它…