传送门

解法一:树链剖分+二分+差分

  树链剖分快速求解任意两点间的路径的权值和;

  然后,二分答案;

  此题的难点是如何快速求解重合路径?

  差分数组可以否???

  在此之前先介绍一下相关变量:

 int fa[maxn];
int siz[maxn];//siz[i]:i子树的节点个数
int dep[maxn];//dep[i]:节点i在树中的深度
int son[maxn];//son[i]:节点i的重儿子
int w[maxn];//w[i]:i节点与其父节点的权值
int tid[maxn];//tid[i]:节点i的新编号
int top[maxn];//top[i]:节点i所在重链的祖先
int s[maxn];//s[i]:新编号中,[1,i]的权值之和,s[i]=w[1]+w[2]+...+w[i];

  如何用差分数组求解重合路径呢?

  考虑一下化简得题型,给定 n 个数;

  给出 m 个区间 [L,R] ,如何求着 m 个区间公共覆盖的点?

  例如 n = 10 , m = 4;

     [2,8],[3,7],[4,6],[5,6]

     这四个区间得公共覆盖得区间点为 5,6;

  定义diff[ ]为差分数组。

  对于给出得区间[L,R] , diff[L]++,diff[R+1]--;

  最后扫一遍diff[] ,求出diff[]得前缀和sum[];

  如果存在点 x 使得 sum[x] = m,那么点 x 就是这 m 个区间公共覆盖的点;

  此题同理,求出不满足二分条件得 cnt 个区间[L,R],通过diff[]求出这 cnt 个区间公共覆盖的点;

  代码如下:

 int diff[maxn];
void Update(int u,int v)
{
int x=top[u];
int y=top[v];
if(x == y)//如果 u,v 在同一条重链上
{
if(dep[u] > dep[v])
swap(u,v);
//节点son[u]到节点v的新编号是连续的
diff[tid[son[u]]]++;
diff[tid[v]+]--;
return ;
}
else//如果不在
{
if(dep[x] > dep[y])
{
swap(x,y);
swap(u,v);
}
//节点 top[v]与节点v的新编号是连续的
diff[tid[y]]++;
diff[tid[v]+]--;
Update(u,fa[y]);
}
}

AC代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=3e5+; int n,m;
int fa[maxn];
int siz[maxn];//siz[i]:i子树的节点个数
int dep[maxn];
int son[maxn];//son[i]:节点i的重儿子
int w[maxn];//w[i]:i节点与其父节点的权值
int tid[maxn];//tid[i]:节点i的新编号
int top[maxn];//top[i]:节点i所在重链的祖先
int s[maxn];//s[i]:新编号中,[1,i]的权值之和,s[i]=w[1]+w[2]+...+w[i];
int num;
int head[maxn];
struct Edge
{
int to;
int w;
int next;
}G[*maxn];
void addEdge(int u,int v,int w)
{
G[num].to=v;
G[num].w=w;
G[num].next=head[u];
head[u]=num++;
}
struct Que
{
int u,v;
int w;
}que[maxn];
void DFS1(int u,int f,int d)
{
fa[u]=f;
dep[u]=d;
siz[u]=;
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(v == f)
continue; w[v]=G[i].w;
DFS1(v,u,d+); siz[u] += siz[v];
if(son[u] == - || siz[v] > siz[son[u]])
son[u]=v;
}
}
void DFS2(int u,int a,int &k)
{
top[u]=a;
tid[u]=++k;
s[k]=s[k-]+w[u];
if(son[u] == -)
return ;
DFS2(son[u],a,k);
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(v != son[u] && v != fa[u])
DFS2(v,v,k);
}
}
int Find(int u,int v)//求解节点u到节点v的路径权值和
{
int x=top[u];
int y=top[v];
int ans=; while(x != y)
{
if(dep[x] > dep[y])
{
swap(u,v);
swap(x,y);
}
ans += s[tid[v]]-s[tid[y]-];
v=fa[y];
y=top[v];
}
if(u != v)
{
if(dep[u] > dep[v])
swap(u,v);
ans += s[tid[v]]-s[tid[u]];
} return ans;
} int diff[maxn];
void Update(int u,int v)
{
int x=top[u];
int y=top[v];
if(x == y)//如果 u,v 在同一条重链上
{
if(dep[u] > dep[v])
swap(u,v);
//节点son[u]到节点v的新编号是连续的
diff[tid[son[u]]]++;
diff[tid[v]+]--;
return ;
}
else//如果不在
{
if(dep[x] > dep[y])
{
swap(x,y);
swap(u,v);
}
//节点 top[v]与节点v的新编号是连续的
diff[tid[y]]++;
diff[tid[v]+]--;
Update(u,fa[y]);
}
}
/**
cnt:一共有cnt个权值和 > mid
ans1:这cnt个权值和最大的比mid大多少
ans2:这cnt个路径中权值最大的公共路径
*/
bool Check(int mid)
{
int cnt=;
int ans1=;
for(int i=;i <= m;++i)
{
int u=que[i].u;
int v=que[i].v;
if(que[i].w > mid)
{
cnt++;
ans1=max(ans1,que[i].w-mid);
Update(u,v);
}
}
int ans2=;
int tot=;
for(int i=;i <= n;++i)
{
tot += diff[i];
diff[i]=;
if(tot == cnt)
ans2=max(ans2,s[i]-s[i-]);
}
//只有ans2 >= ans1 才能够使最大的权值和小于等于mid
return ans2 >= ans1;
}
int Solve()
{
DFS1(,,);
int k=;
DFS2(,,k); for(int i=;i <= m;++i)
{
int u=que[i].u;
int v=que[i].v;
que[i].w=Find(u,v);
} int l=-,r=+;
while(r-l > )//二分答案
{
int mid=l+((r-l)>>);
if(Check(mid))
r=mid;
else
l=mid;
}
return r;
}
void Init()
{
num=;
mem(head,-);
mem(diff,);
mem(son,-);
mem(s,);
}
int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\BZOJ\\4326.in","r",stdin);
while(~scanf("%d%d",&n,&m))
{
Init();
for(int i=;i < n;++i)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,w);
}
for(int i=;i <= m;++i)
scanf("%d%d",&que[i].u,&que[i].v); printf("%d\n",Solve());
}
return ;
}

解法二:树上差分+LCA+二分

  差分详解,戳这里

bzoj 4326: NOIP2015 运输计划(二分+树链剖分)的更多相关文章

  1. bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】

    常数巨大,lg上开o2才能A 首先预处理出运输计划的长度len和lca,然后二分一个长度w,对于长度大于w的运输计划,在树上差分(d[u]+1,d[v]+1,d[lca]-2),然后dfs,找出所有覆 ...

  2. NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)

    BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...

  3. BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1930  Solved: 1231[Submit][Statu ...

  4. BZOJ 4326: NOIP2015 运输计划(二分,树上差分)

    Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1945  Solved: 1243[Submit][Status][Discuss] Descript ...

  5. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  6. BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1388  Solved: 860 [Submit][Stat ...

  7. bzoj 4326: NOIP2015 运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...

  8. 【NOIP 2015 DAY2 T3】 运输计划 (树链剖分-LCA)

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...

  9. [noip 2015]运输计划 [LCA][树链剖分]

    用了luogu上的题目描述 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的 ...

随机推荐

  1. No module named 'ConfigParser'

    系统: CentOS-6.4-x86_64 Python : Python 3.4.5 和 Python 3.5.2 安装 MySQL-python ,结果出错: ImportError: No mo ...

  2. window.location.href ie 不兼容问题

    今天再做项目演示的时候,用的是ie浏览器报错404,项目都运行好久了,第一次用ie就这样了悲剧,贴下解决方法吧 function getContextPath() { var pathName = d ...

  3. LODOP打印安装到win的特殊字体

    LODOP能够打印的字体,来源于安装到本机windows里字体库的字体,如果需要打印特别的字体,需要在该操作系统安装.由于web网站的用户千差万别,字体库也有不同,但是一般常见的字体都是有的,因此做模 ...

  4. MySQL启动错误---发生系统错误/系统找不到指定的文件。

    今天启动mysql时,突然报错发生系统错误,系统找不到指定的文件.当时有点懵,安装mysql 之后,一直就没有修改过,怎么会报错呢?上网搜索了一下,重新安装一下mysql服务就可以了,现在也不知道什么 ...

  5. Django通用视图APIView和视图集ViewSet的介绍和使用

    原 Django通用视图APIView和视图集ViewSet的介绍和使用 2018年10月21日 14:42:14 不睡觉假扮古尔丹 阅读数:630   1.APIView DRF框架的视图的基类是 ...

  6. delegate--委托

    delegate--委托 (可以把委托看成用来执行方法的一个东西) eg: namespace delegateTest{ delegate double MathsOp(double x); cla ...

  7. CodeForces615B-Longtail Hedgehog-dp/图

    记忆化数组记录从这个点的最长下降序列,然后乘以这个点的度,就是ans,维护即可. #include <cstdio> #include <cstring> #include & ...

  8. 关闭VS2017脚本调试 已启用 Visual Studio 中的 Chrome 脚本调试

    转载:https://blog.csdn.net/lilinoscar/article/details/79114721 每当调试项目时,都是重新打开一个浏览器窗口,而且关闭调试后,也会关闭窗口,很麻 ...

  9. [踩过的坑]Elasticsearch.Net 官网示例的坑

    经过昨天的ElasticSearch 安装,服务以及可以启动了,接下来就可以开发了,找到了官网提供的API以及示例,Es 官方提供的.net 客户端有两个版本一个低级版本: [Elasticsearc ...

  10. Cetos 7 系统安装备注事项

    说明:此篇内容为个人记录备注事项,具体的安装操作请参考其他教程: 系统安装: 公司的服务器型号为戴尔R330 卡片式服务器,安装过程中遇到一些问题,此文章中简单记录下 1.下载一份Cetos 系统镜像 ...