bzoj4326
二分+树剖+差分
之前的做法naive,莫名其妙的wa,明明uoj95分
看到最小最大上二分,树上路径问题直接剖,然后问题就转化成了一个判定问题,每次二分出最长路径长度,问能不能达到。那么我们就把所有长度大于二分出的d的路径拉出来,求出他们公共路径的最大长度,看减去能不能满足。那么现在的问题就转化成了求路径的交。我们可以利用bzoj4390的树上差分的方法解决,我们先把边转化为点,即每条边等价于他连接的深度较深的点,那么我们利用树上差分标记路径上的边,把路径上的边标记+1,这个我们只要在u,v,+1,lca,-2就行了,然后我们求一个前缀和,看子树权值是否等于路径数量就行了。
树上差分是一种重要的思想,大概有几种方法,
1.像这道题和bzoj4390,可以标记路径上的点/边
2.像noip2016day1t2,雨天的尾巴,利用树剖重链是一段连续的区间且最多只有log条重链,我们可以log时间修改路径的信息,这和上面的差分是不一样的,因为如果按上面的方法差分那么可能会把这条路径上的信息带到其他的点,而树剖保证dfs序连续,所以每条重链差分一下,那么就不会带入到其他点,这样一共会打logn个标记
原先是像魔法森林那样把边权转化为点权,时间爆炸
#include<bits/stdc++.h>
using namespace std;
const int N = ;
struct edge {
int nxt, to, w;
} e[N << ];
struct path {
int u, v, w;
bool friend operator < (path a, path b) { return a.w > b.w; }
} a[N];
namespace IO
{
const int Maxlen = N * ;
char buf[Maxlen], *C = buf;
int Len;
inline void read_in()
{
Len = fread(C, , Maxlen, stdin);
buf[Len] = '\0';
}
inline void fread(int &x)
{
x = ;
int f = ;
while (*C < '' || '' < *C) { if(*C == '-') f = -; ++C; }
while ('' <= *C && *C <= '') x = (x << ) + (x << ) + *C - '', ++C;
x *= f;
}
inline void read(int &x)
{
x = ;
int f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = (x << ) + (x << ) + c - ''; c = getchar(); }
x *= f;
}
inline void read(long long &x)
{
x = ;
long long f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = (x << 1ll) + (x << 3ll) + c - ''; c = getchar(); }
x *= f;
}
} using namespace IO;
int n, m, cnt = , tot, lim;
int tree[N], mark[N], mir[N], head[N], dis[N], size[N], son[N], dep[N], fa[N], top[N], Lca[N], w[N], in[N], out[N];
void link(int u, int v, int w)
{
e[++cnt].nxt = head[u];
head[u] = cnt;
e[cnt].to = v;
e[cnt].w = w;
}
void dfs(int u, int last)
{
size[u] = ;
dis[u] = dis[last] + w[u];
for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last)
{
dep[e[i].to] = dep[u] + ;
fa[e[i].to] = u;
w[e[i].to] = e[i].w;
dfs(e[i].to, u);
size[u] += size[e[i].to];
if(size[e[i].to] > size[son[u]]) son[u] = e[i].to;
}
}
void dfs(int u, int acs, int last)
{
in[u] = ++tot;
mir[tot] = u;
top[u] = acs;
if(son[u]) dfs(son[u], acs, u);
for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last && e[i].to != son[u]) dfs(e[i].to, e[i].to, u);
out[u] = tot;
}
int lca(int u, int v)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
int Dis(int u, int v)
{
int x = lca(u, v);
return dis[u] + dis[v] - * dis[x];
}
void update(int x, int d)
{
for(; x <= n; x += x & (-x)) tree[x] += d;
}
int query(int x)
{
int ret = ;
for(; x; x -= x & (-x)) ret += tree[x];
return ret;
}
bool check(int d)
{
memset(mark, , sizeof(mark));
int cou = , mx = ;
for(int i = ; i <= m; ++i)
{
if(a[i].w <= d) break;
++cou;
mark[in[Lca[i]]] -= ;
++mark[in[a[i].u]];
++mark[in[a[i].v]];
}
for(int i = ; i <= n; ++i) mark[i] += mark[i - ];
for(int i = ; i <= n; ++i)
{
int tmp = mark[out[i]] - mark[in[i] - ];
if(tmp == cou) mx = max(mx, w[i]);
}
return a[].w - mx <= d;
}
int main()
{
read_in();
fread(n);
fread(m);
for(int i = ; i < n; ++i)
{
int u, v, w;
fread(u);
fread(v);
fread(w);
link(u, v, w);
link(v, u, w);
}
dfs(, );
dfs(, , );
for(int i = ; i <= m; ++i)
{
fread(a[i].u);
fread(a[i].v);
a[i].w = Dis(a[i].u, a[i].v);
lim = max(lim, a[i].w);
}
sort(a + , a + m + );
for(int i = ; i <= m; ++i) Lca[i] = lca(a[i].u, a[i].v);
int l = -, r = lim + , ans = ;
while(r - l > )
{
int mid = (l + r) >> ;
if(check(mid)) r = ans = mid;
else l = mid;
}
printf("%d\n", ans);
return ;
}
bzoj4326的更多相关文章
- [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划
[BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划 试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− ...
- 【bzoj4326】[NOIP2015]运输计划
题目描述 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该 ...
- NOIP2015 运输计划(bzoj4326)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 886 Solved: 574[Submit][Status] ...
- [bzoj4326][NOIP2015]运输计划
Description 公元2044年,人类进入了宇宙纪元. 国有个星球,还有条双向航道,每条航道建立在两个星球之间,这条航道连通了国的所有星球. 小掌管一家物流公司,该公司有很多个运输计划,每个运输 ...
- 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 703 Solved: 461[Submit][Status] ...
- bzoj4326 运输计划
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n ...
- NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告
前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...
- bzoj4326 树链剖分 + 线段树 // 二分 lca + 树上差分
https://www.lydsy.com/JudgeOnline/problem.php?id=4326 题意:N个点的树上给M条树链,问去掉一条边的权值之后所有树链长度和的最大值最小是多少. 首先 ...
- BZOJ4326或洛谷2680 运输计划
BZOJ原题链接 洛谷原题链接 用\(LCA\)初始化出所有运输计划的原始时间,因为答案有单调性,所以二分答案,然后考虑检验答案. 很容易想到将所有超出当前二分的答案的运输计划所经过的路径标记,在这些 ...
- 2018.09.26 bzoj4326: NOIP2015 运输计划(二分+树上差分)
传送门 简单树上操作. 先转边权为点权. 显然所有的询问操作对应的路径会有一些交点,那么我们可以直接二分答案,对于所有大于二分值的询问用树上差分维护,最后dfs一遍每个点被覆盖了几次,当前情况合法当且 ...
随机推荐
- 【BZOJ3626】LCA(树上差分,树链剖分)
题意:给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询问给 ...
- python学习之-项目开发目录规范
软件目录结构规范有什么好处: 通过规范化,能够更好的控制软件结构,让程序具有更高的可读性. 项目目录组织结构如下: Foo/ # 项目名 --bin/ # 可执行文件目录 --foo # 可执行程序 ...
- 为什么utf8占用3个字节
UNICODE是万能编码,包含了所有符号的编码,它规定了所有符号在计算机底层的二进制的表示顺序.有关Unicode为什么会出现就不叙述了,Unicode是针对所有计算机的使用者定义一套统一的编码规范, ...
- HDU 5573 Binary Tree【构造】
几天前模拟区域赛的一道题,今天发现在草稿箱里直接补个博客. 感觉这还是一道很有意思的构造题. 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 ...
- Jquery操作事件
1.文档加载事件 2.DOM单击双击事件 3.DOM获得焦点,失去焦点问题 4.DOM鼠标移入,移出事件 <!DOCTYPE html> <html> <head> ...
- 扫描仪共享工具(BlindScanner Pro) 3.23 特别版
http://www.xdowns.com/soft/1/126/2014/Soft_125206.html
- 学习swift从青铜到王者之Swift语言函数05
1.定义一个函数以及调用 //一,定义一个无参无返回值函数 func fun1(){ print("this is first function") } fun1() 2.定义一个 ...
- 新手玩个人server(阿里云)续二
小二班一番厮杀:那英四强诞生:大家闺秀,小家碧玉.窈窕淑女,妍姿俊俏 .不解释! ?不行! 陈冰,李嘉格,刘明湘.张碧晨.大多数的时候,仅仅要脸好看,一切都那么自热而然的顺理成章. 尽管网上骂声四起, ...
- LoadRunner关联需要转义的常见字符
转义字符总结 在做手动关联时,取边界值的时候,会经常用到转义字符,现将转义字符整理如下: \b 退格 \f 换页 \n 换行 \ ...
- poj1664 dp记忆化搜索
http://poj.org/problem?id=1664 Description 把M个相同的苹果放在N个相同的盘子里,同意有的盘子空着不放,问共同拥有多少种不同的分法?(用K表示)5.1.1和1 ...