[BZOJ4326][NOIP2015]运输计划(二分答案+树上差分)
2017-08-25 23:14
465 查看
首先存下每个运输计划的起点st[i],终点ed[i],最近公共祖先lca[i]以及耗时len[i]。
先二分最短时间time。
在判定中,先标记出所有len[i]>time的运输计划,虫洞必须位于这些运输计划的路径的公共边上。
这里,为每个点赋予一个权值,初始为0。
然后对于任意一个len[i]>time的运输计划,把st[i]−>ed[i]的路径上的所有点(lca[i]除外)的点权,全部加上1,
这样容易知道,最后如果一个点的点权等于所有len[i]>time的运输计划的个数,那么连接这个点和这个点的父亲的边被改造成虫洞后会降低所有len[i]>time的运输计划的耗时,降低量为这条边的边权。所以,在符合条件的边中,选取一条边权最大的边,判断是否:耗时最长的计划消耗的时间−选取的边的边权<=time。
对于路径加1的操作,可以使用树剖实现,但是常数较大。但是可以发现这里的询问都是单点询问,而且都在路径修改之后。对于这一点,可以使用差分数组代替树剖,将复杂度去掉一个log。
建立差分数组b[u]=val[u]−∑val[v],其中val[u]为u的点权,v为u的子节点。
对于u−>v的路径加x(不含lca)的操作为:b[u]+=x,b[v]+=x,b[lca]−=x∗2。
而单点询问就是求子树和。最后DFS一遍就可以求出所有点的点权。
代码:
先二分最短时间time。
在判定中,先标记出所有len[i]>time的运输计划,虫洞必须位于这些运输计划的路径的公共边上。
这里,为每个点赋予一个权值,初始为0。
然后对于任意一个len[i]>time的运输计划,把st[i]−>ed[i]的路径上的所有点(lca[i]除外)的点权,全部加上1,
这样容易知道,最后如果一个点的点权等于所有len[i]>time的运输计划的个数,那么连接这个点和这个点的父亲的边被改造成虫洞后会降低所有len[i]>time的运输计划的耗时,降低量为这条边的边权。所以,在符合条件的边中,选取一条边权最大的边,判断是否:耗时最长的计划消耗的时间−选取的边的边权<=time。
对于路径加1的操作,可以使用树剖实现,但是常数较大。但是可以发现这里的询问都是单点询问,而且都在路径修改之后。对于这一点,可以使用差分数组代替树剖,将复杂度去掉一个log。
建立差分数组b[u]=val[u]−∑val[v],其中val[u]为u的点权,v为u的子节点。
对于u−>v的路径加x(不含lca)的操作为:b[u]+=x,b[v]+=x,b[lca]−=x∗2。
而单点询问就是求子树和。最后DFS一遍就可以求出所有点的点权。
代码:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res; } const int N = 3e5 + 5, LogN = 23; int n, m, a , ecnt, nxt[N << 1], adj , go[N << 1], fa [LogN], dep , T , val[N << 1], dis , len , st , ed , maxv, _lca , top , v_res, cnt_now; void add_edge(int u, int v, int w) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; val[ecnt] = w; } void dfs(int u, int fu) { int i; dep[u] = dep[fu] + 1; for (i = 1; i <= 21; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; for (int e = adj[u], v; e; e = nxt[e]) { if ((v = go[e]) == fu) continue; fa[v][0] = u; dis[v] = dis[u] + val[e]; top[v] = val[e]; dfs(v, u); } } int lca(int u, int v) { int i; if (dep[u] < dep[v]) swap(u, v); for (i = 21; i >= 0; i--) { if (dep[fa[u][i]] >= dep[v]) u = fa[u][i]; if (u == v) return u; } for (i = 21; i >= 0; i--) if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i]; return fa[u][0]; } int dist(int i, int u, int v) { return dis[u] + dis[v] - (dis[_lca[i] = lca(u, v)] << 1); } void change(int i, int x) { T[st[i]] += x; T[ed[i]] += x; T[_lca[i]] -= x << 1; } int dfs_ans(int u, int fu) { int res_d = T[u]; for (int e = adj[u], v; e; e = nxt[e]) { if ((v = go[e]) == fu) continue; res_d += dfs_ans(v, u); } if (res_d == cnt_now) v_res = max(v_res, top[u]); return res_d; } bool check(int mid) { int i, res = 0; for (i = 0; i <= n; i++) T[i] = 0; cnt_now = 0; for (i = 1; i <= m; i++) if (len[i] > mid) cnt_now++, change(i, 1); if (!cnt_now) return 1; v_res = 0; dfs_ans(1, 0); return maxv - v_res <= mid; } int solve() { int l = 0, r = maxv, mid; while (l <= r) { mid = l + r >> 1; if (check(mid)) r = mid - 1; else l = mid + 1; } return l; } int main() { int i, x, y, z; n = read(); m = read(); for (i = 1; i < n; i++) { x = read(); y = read(); z = read(); add_edge(x, y, z); add_edge(y, x, z); } dfs(1, 0); for (i = 1; i <= m; i++) { st[i] = read(); ed[i] = read(); len[i] = dist(i, st[i], ed[i]); maxv = max(maxv, len[i]); } printf("%d\n", solve()); return 0; }
相关文章推荐
- BZOJ 4326: NOIP2015 运输计划 二分答案 树上差分
- bzoj 4326: NOIP2015 运输计划【树链剖分+二分+树上差分】
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
- 【BZOJ】4326 NOIP2015 运输计划 二分+LCA+树上差分
- 【BZOJ4326】【二分答案】【树上差分】NOIP2015 D2T3 运输计划 题解
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- bzoj4326【2015提高】运输计划(二分答案+lca+树上差分前缀和)
- [BZOJ4326][NOIP2015]运输计划(二分+dfs序+树上差分)
- 【bzoj 4326】【codevs 4632】【UOJ #150】[NOIP 2015]运输计划(dfs+lca+二分答案+差分)
- LuoguP2680/UOJ150[NOIP2015] 运输计划 解题报告【二分答案+树上操作(LCA)+树上差分】
- [BZOJ4326][NOIP2015][倍增][二分][差分序列]运输计划
- 【bzoj4326】[NOIP2015]运输计划 二分答案+LCA
- bzoj 4326: NOIP2015 运输计划 (二分答案+树链剖分+树状数组)
- 【NOIP2015】【bzoj4326】运输计划 LCA+差分+二分答案
- [二分+差分]BZOJ 4326——NOIP2015 运输计划
- bzoj4326 & UOJ150【NOIP2015】运输计划 ( 树上差分 + lca )
- NOIP2015 运输计划 二分答案+Tarjan LCA+树上差分
- BZOJ 4326: NOIP2015 运输计划【LCA】【二分】【差分】
- BZOJ[4326][NOIP2015]运输计划 二分答案+树链剖分+差分
- 【NOIP2015】运输计划(树上差分,二分答案)