题目大意:
  给出一个$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的更多相关文章

  1. 【CF526G】Spiders Evil Plan(贪心)

    [CF526G]Spiders Evil Plan(贪心) 题面 洛谷 CodeForces 给定一棵树,要求选择\(y\)条链,满足被链覆盖的所有点在树上联通,且\(x\)必定在联通块中. 对于每次 ...

  2. CF Contest 526 G. Spiders Evil Plan 长链剖分维护贪心

    LINK:Spiders Evil Plan 非常巧妙的题目. 选出k条边使得这k条边的路径覆盖x且覆盖的边的边权和最大. 类似于桥那道题还是选择2k个点 覆盖x那么以x为根做长链剖分即可. 不过这样 ...

  3. Codeforces 526G Spiders Evil Plan

    由于做的时候看的是中文题面,第一遍写就被卡题意了:还以为每一条都要过x,那么就是一道动态树根选择2y个叶子的奇怪题目 交完0分gg,才发现题目看错了╮(╯▽╰)╭ the node containin ...

  4. Codeforces 526G - Spiders Evil Plan(长链剖分+直径+找性质)

    Codeforces 题目传送门 & 洛谷题目传送门 %%%%% 这题也太神了吧 storz 57072 %%%%% 首先容易注意到我们选择的这 \(y\) 条路径的端点一定是叶子节点,否则我 ...

  5. 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 ...

  6. 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 ...

  7. 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 ...

  8. 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 ...

  9. 【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 ...

随机推荐

  1. Kd-Tree&Ransac笔记

    关于sift资源总结: http://blog.csdn.net/masibuaa/article/details/9191309 两个比较好的资源: https://my.oschina.net/k ...

  2. PHP基础壹

    <?php //<!--//注释方式-->//<!--//echo 后面跟字符串:-->//<!--print("123");-->//& ...

  3. Android事件分发机制详解(2)----分析ViewGruop的事件分发

    首先,我们需要 知道什么是ViewGroup,它和普通的View有什么区别? ViewGroup就是一组View的集合,它包含很多子View和ViewGroup,是Android 所有布局的父类或间接 ...

  4. SQLEXPRESS 2012 安装NorthWind和Pub数据库

    安装SQL后,学习时总是没有这两个示例数据库. 先从微软那里下载此文件. 网址:http://www.microsoft.com/en-us/download/details.aspx?id=2365 ...

  5. hdu 1512

    思路:用并查集即可,每次合并的时候将小的集合合并到大的集合上去.理论上的平均复杂度是n*lgn*lgn. #include<map> #include<queue> #incl ...

  6. Codeforces 938.B Run For Your Prize

    B. Run For Your Prize time limit per test 1 second memory limit per test 256 megabytes input standar ...

  7. Lesson 7: C#多线程

    C#多线程 1.适用于: 通过网络进行通信 执行占用时间的操作 区分具有不同优先级的任务 使用户界面在执行后台任务时能快速响应用户的交互 2.Thread类常用属性及方法 属性: IsAlive:显示 ...

  8. sql server创建外键,子母表,级联删除。

    级联删除. 最近建一个合同关系,在原有的资产平台上添加维保合同关系,维保合同问题, 需要在后面添加资产的维保合同,使用ef,该添加的冗余字段都已经添加上了,现在做这个,删除的时候只删了主表提示出问题, ...

  9. [bzoj1051][HAOI2006]受欢迎的牛——强连通分量

    题目大意: 给定一个有向图,求能够被其他所有点访问到的点的个数. 题解: 首先,这个题我在洛谷上AC了,但是bzoj上WA,不知道为什么. 说一下解法. 首先,我们进行scc分解,可以知道, 如果一个 ...

  10. JS将JSON日期转换为指定格式的日期

    1.引入JS日期转换的函数库 function Format(now,mask) { var d = now; var zeroize = function (value, length) { if ...