[CF526G]Spiders Evil Plan
题目大意:
给出一个$n(n\leq 10^5)$个结点的带边权的树,$q(q\leq 10^5)$个询问,每次询问用$y$条路径覆盖整棵树且覆盖$x$至少一次,最多能覆盖的道路长度是多少?
强制在线。
思路:
考虑固定$x$时的情况,我们可以使用长链剖分,然后贪心地选择$2y$条长链,每$2$条可以组成一条路径,这样就找出了$y$条路径的最优方案,均摊复杂度$O(n)$。
现在考虑$x$不固定的情况,对于每个询问分别做一次长链剖分,复杂度是$O(nq)$的,显然会超时。
考虑如何只用一次树剖解决所有的询问。
问题也就变成了如何确定一个根,使得所有询问的覆盖方案中,每条路径都会经过这个根。
显然,经过一点最长的路径肯定会经过直径的一个端点。
因此我们可以将直径的任一端点作为根结点开始树剖,然后贪心地选$2y-1$条最长链(最长的一条本身就是一条路径),这样时间复杂度就是$O(n+q)$。
但是这样并不是完全正确的,因为$2y-1$条最长链不一定能涵盖$x$。
因此我们需要将其中一条替换成一条经过$x$的链。
具体分为以下三种情况:
1.直接把最短的一整条链去掉;
2.把从根结点出发的一条链去掉上面一半;
3.把离$x$最近的一条链去掉下面$y$一半。
- #include<queue>
- #include<cstdio>
- #include<cctype>
- #include<vector>
- #include<algorithm>
- inline int getint() {
- register char ch;
- while(!isdigit(ch=getchar()));
- register int x=ch^'';
- while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
- return x;
- }
- const int N=;
- struct Edge {
- int to,w;
- };
- bool vis[N];
- std::queue<int> q;
- std::vector<Edge> e[N];
- int dis[N],far[N],par[N],top[N],son[N],leaf[N],rank[N],sum[N],root;
- inline void add_edge(const int &u,const int &v,const int &w) {
- e[u].push_back((Edge){v,w});
- e[v].push_back((Edge){u,w});
- }
- inline void bfs() {
- q.push(root=);
- vis[]=true;
- while(!q.empty()) {
- const int x=q.front();
- q.pop();
- if(dis[x]>dis[root]) root=x;
- for(register unsigned i=;i<e[x].size();i++) {
- const int &y=e[x][i].to,&w=e[x][i].w;
- if(vis[y]) continue;
- dis[y]=dis[x]+w;
- vis[y]=true;
- q.push(y);
- }
- }
- dis[root]=;
- }
- void dfs1(const int &x,const int &par) {
- son[x]=;
- ::par[x]=par;
- far[x]=dis[x];
- for(unsigned i=;i<e[x].size();i++) {
- const int &y=e[x][i].to,&w=e[x][i].w;
- if(y==par) continue;
- dis[y]=dis[x]+w;
- dfs1(y,x);
- if(far[y]>far[x]) {
- far[x]=far[y];
- son[x]=y;
- }
- }
- }
- void dfs2(const int &x) {
- if(x==son[par[x]]) {
- top[x]=top[par[x]];
- } else {
- top[x]=x;
- }
- if(son[x]) {
- dfs2(son[x]);
- } else {
- leaf[++leaf[]]=x;
- }
- for(unsigned i=;i<e[x].size();i++) {
- const int &y=e[x][i].to;
- if(y==par[x]||y==son[x]) continue;
- dfs2(y);
- }
- }
- inline bool cmp(const int &x,const int &y) {
- return dis[x]-dis[par[top[x]]]>dis[y]-dis[par[top[y]]];
- }
- inline int query(const int &x,const int &y) {
- if(rank[top[x]]<=y*-) {
- return sum[std::min(y*-,leaf[])];
- }
- int u=x;
- while(rank[top[u]]>y*-) {
- u=par[top[u]];
- }
- return sum[y*-]-std::min(std::min(sum[y*-]-sum[y*-],far[u]-dis[u]),dis[u])+(far[x]-dis[u]);
- }
- int main() {
- const int n=getint(),q=getint();
- for(register int i=;i<n;i++) {
- const int u=getint(),v=getint(),w=getint();
- add_edge(u,v,w);
- }
- bfs();
- dfs1(root,);
- dfs2(root);
- std::sort(&leaf[],&leaf[+leaf[]],cmp);
- for(register int i=;i<=leaf[];i++) {
- rank[top[leaf[i]]]=i;
- sum[i]=sum[i-]+dis[leaf[i]]-dis[par[top[leaf[i]]]];
- }
- for(register int i=,ans=;i<q;i++) {
- const int x=(getint()+ans-)%n+,y=(getint()+ans-)%n+;
- printf("%d\n",ans=query(x,y));
- }
- return ;
- }
[CF526G]Spiders Evil Plan的更多相关文章
- 【CF526G】Spiders Evil Plan(贪心)
[CF526G]Spiders Evil Plan(贪心) 题面 洛谷 CodeForces 给定一棵树,要求选择\(y\)条链,满足被链覆盖的所有点在树上联通,且\(x\)必定在联通块中. 对于每次 ...
- CF Contest 526 G. Spiders Evil Plan 长链剖分维护贪心
LINK:Spiders Evil Plan 非常巧妙的题目. 选出k条边使得这k条边的路径覆盖x且覆盖的边的边权和最大. 类似于桥那道题还是选择2k个点 覆盖x那么以x为根做长链剖分即可. 不过这样 ...
- Codeforces 526G Spiders Evil Plan
由于做的时候看的是中文题面,第一遍写就被卡题意了:还以为每一条都要过x,那么就是一道动态树根选择2y个叶子的奇怪题目 交完0分gg,才发现题目看错了╮(╯▽╰)╭ the node containin ...
- Codeforces 526G - Spiders Evil Plan(长链剖分+直径+找性质)
Codeforces 题目传送门 & 洛谷题目传送门 %%%%% 这题也太神了吧 storz 57072 %%%%% 首先容易注意到我们选择的这 \(y\) 条路径的端点一定是叶子节点,否则我 ...
- code forces 383 Arpa's loud Owf and Mehrdad's evil plan(有向图最小环)
Arpa's loud Owf and Mehrdad's evil plan time limit per test 1 second memory limit per test 256 megab ...
- Arpa's loud Owf and Mehrdad's evil plan
Arpa's loud Owf and Mehrdad's evil plan time limit per test 1 second memory limit per test 256 megab ...
- Codeforces Round #383 (Div. 2)C. Arpa's loud Owf and Mehrdad's evil plan
C. Arpa's loud Owf and Mehrdad's evil plan time limit per test 1 second memory limit per test 256 me ...
- Codeforces Round #383 (Div. 2) C. Arpa's loud Owf and Mehrdad's evil plan —— DFS找环
题目链接:http://codeforces.com/contest/742/problem/C C. Arpa's loud Owf and Mehrdad's evil plan time lim ...
- 【codeforces 742C】Arpa's loud Owf and Mehrdad's evil plan
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
随机推荐
- Nodejs的那些事
前言: Node.js实际上是算是个前端开发,但是我们要做APP自动化涉及到 node.js ,也需要它来帮我们安装一些 packing 一.Node.js安装 1.安装Node.js:立即下载 2. ...
- python基础实践(五)
# -*- coding:utf-8 -*-# Author:sweeping-monk# -*-操作列表-*-Traverse_the_list = ['guanfu','xiaole','fang ...
- Python全栈工程师(元组、字典)
ParisGabriel 感谢 大家的支持 你们的阅读评价就是我最好的更新动力 我会坚持吧排版做的越来越好 每天坚持 一天一篇 点个订阅吧 灰常感谢 当个死粉也阔以 ...
- centos 7 安装codeblocks
CentOS7安装Code::Blocks 在CentOS7上安装Codelocks的过程. 1.安装gcc,需要c和c++两部分,默认安装下,CentOS不安装编译器的,在终端输入以下命令即可yum ...
- 【2017】KK English
2017/11/24 Regardless of the enormous amount of photos shared on Wechat or Face book, modern city dw ...
- 批量部署ssh免密登陆
#!/bin/bash#set -xservers="10.254.192.xx10.254.192.xx10.254.192.xx"passwd="xxxxxxxx&q ...
- P3456 [POI2007]GRZ-Ridges and Valleys
题意翻译 给定一个地图,为小朋友想要旅行的区域,地图被分为n*n的网格,每个格子(i,j) 的高度w(i,j)是给定的.若两个格子有公共顶点,那么他们就是相邻的格子.(所以与(i,j)相邻的格子有(i ...
- GYM - 101147 K.Touristic Trip
题意: 一个人从城市0开始旅行.一共有N座城市,他每到一座城市都会寄一张明信片.给出从一座城市到另一座城市的概率和在每座城市寄出每张明信片的概率.给出长度为k的寄明信片的序列.问在该序列的条件下在第Z ...
- Hash表模板
namespace Hash { ; ; struct adj { ll nxt,v,num,val; }e[N]; ll head[H],ecnt=; void init() { ecnt=; me ...
- JavaScript jQuery 中定义数组与操作及jquery数组操作 http://www.jb51.net/article/76601.htm
首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象Javascript不支持多 ...