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一遍每个点被覆盖了几次,当前情况合法当且 ...
随机推荐
- 人生第一场CTF的解题报告(部分)
解题报告 濮元杰部分: 王者归来: 120 场景 小王入职了一段时间,最近有点无聊.Web安全项目不多,白天看着其他项目组的同事忙得热火朝天,小王有点坐不住了,这也许是新人都会有的想法,乐于助人.想到 ...
- C#中对字符串的加密和解密
加密: /// <summary> /// 对字符串进行加密 /// </summary> /// <param name="proclaimText" ...
- BZOJ1704: [Usaco2007 Mar]Face The Right Way 自动转身机
n<=5000个数0或1,每次可以连续对固定长度区间取反,目标把所有1变0,求一个取反区间的固定长度K使取反次数最少. 答案关于K不单调,因此枚举K,对每个K扫一遍区间,遇到1就把连续K个数反转 ...
- Javascript 检查字符串是否是数字的几种方法
//判断是否是正整数 function IsNum(s) { if(s!=null){ var r,re; re = /\d*/i; //\d表示数字,*表示匹配多个数字 r = s.match(re ...
- [bzoj4006][JLOI2015]管道连接_斯坦纳树_状压dp
管道连接 bzoj-4006 JLOI-2015 题目大意:给定一张$n$个节点$m$条边的带边权无向图.并且给定$p$个重要节点,每个重要节点都有一个颜色.求一个边权和最小的边集使得颜色相同的重要节 ...
- 胜利大逃亡--hdu --1253(bfs)
Problem Description Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C ...
- try catch finally执行顺序 (return / 变量覆盖)
finally有return 始终返回finally中的return 抛弃 try 与catch中的return 情况1:try{} catch(){}finally{} return x; try{ ...
- MongoDB学习day09--Mongoose aggregate 多表关联查询
Mongodb的aggregate应用之前已经说过了. 可以参考day06 Mongoose的aggregate函数应用 var mongoose=require('./db.js'); var Or ...
- 深度学习综述(LeCun、Bengio和Hinton)
原文摘要:深度学习可以让那些拥有多个处理层的计算模型来学习具有多层次抽象的数据的表示.这些方法在很多方面都带来了显著的改善,包含最先进的语音识别.视觉对象识别.对象检測和很多其他领域,比如药物发现和基 ...
- [PythonCode]扫描局域网的alive ip地址
内网的主机都是自己主动分配ip地址,有时候须要查看下有那些ip在使用,就写了个简单的脚本. linux和windows下都能够用,用多线程来ping1-255全部的地址,效率不高.2分钟左右. 先凑合 ...