题意:

给出一棵树,每条边有一个容量。

有若干次询问:\(S \, T \, K \, A \, B\),求路径\(S \to T\)的最大流量。

有两种方法可以增大流量:

  • 花费\(A\)可以新修一条管道,管道可以连接任意两个点,两个点之间可以有任意条管道连接,新修的管道容量为\(1\)
  • 花费\(B\)可以使某条管道(包括新修的管道)的容量增加\(1\)

求在不超过预算\(K\)的情况下的最大流量。

分析:

注意到流量最大只有\(10^4\),所以我们可以直接在值域上建一棵主席树。

主席树区间维护的是管道的个数以及它们的容量之和,这样方便后面的计算。

首先我们可以求一下路径上的第\(1\)小的容量,这是初始容量。

按照\(A, B\)的大小关系,有两种情况:

  • \(A \leq B\),把所有的经费都用来修建新管道上。因为扩容一次不一定能使流量增加,但是新修管道一定可以增加流量,而且还便宜。
  • \(A > B\),这样就不能随便新建管道了,所以有两种可能:
    • 只新建一条管道,然后再这条新管道上扩容
    • 只在原来的管道上扩容

在求能扩容得到的最大容量可以用二分的思想,往主席树的左右子树走下去。

另:根据题面的数据范围,最终答案可能会爆int的,但是事实证明测试数据中没有这样的数据。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 100000 + 10;
const int M = 20;
int n, m; struct Edge
{
int v, w, nxt;
Edge() {}
Edge(int v, int w, int nxt): v(v), w(w), nxt(nxt) {}
}; int ecnt, head[maxn];
Edge edges[maxn * 2]; void AddEdge(int u, int v, int w) {
edges[ecnt] = Edge(v, w, head[u]);
head[u] = ecnt++;
} struct Node
{
int lch, rch, cnt, sum;
}T[maxn << 5];
int sz, root[maxn]; int update(int pre, int L, int R, int pos) {
int rt = ++sz;
T[rt] = T[pre];
T[rt].cnt++;
T[rt].sum += pos;
if(L < R) {
int M = (L + R) / 2;
if(pos <= M) T[rt].lch = update(T[pre].lch, L, M, pos);
else T[rt].rch = update(T[pre].rch, M+1, R, pos);
}
return rt;
} int query(int u, int v, int l, int L, int R, int k) {
if(L == R) return L;
int M = (L + R) / 2;
int sum = T[T[u].lch].cnt + T[T[v].lch].cnt - T[T[l].lch].cnt * 2;
if(sum >= k) return query(T[u].lch, T[v].lch, T[l].lch, L, M, k);
else return query(T[u].rch, T[v].rch, T[l].rch, M+1, R, k - sum);
} int fa[maxn], dep[maxn]; void dfs(int u) {
for(int i = head[u]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(v == fa[u]) continue;
fa[v] = u;
dep[v] = dep[u] + 1;
root[v] = update(root[u], 0, M, edges[i].w);
dfs(v);
}
} int anc[maxn][20]; void preprocess() {
memset(anc, 0, sizeof(anc));
for(int i = 1; i <= n; i++) anc[i][0] = fa[i];
for(int j = 1; (1 << j) < n; j++)
for(int i = 1; i <= n; i++) if(anc[i][j-1])
anc[i][j] = anc[anc[i][j-1]][j-1];
} int LCA(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
int log;
for(log = 0; (1 << log) < dep[u]; log++);
for(int i = log; i >= 0; i--)
if(dep[u] - (1<<i) >= dep[v]) u = anc[u][i];
if(u == v) return u;
for(int i = log; i >= 0; i--)
if(anc[u][i] && anc[u][i] != anc[v][i])
u = anc[u][i], v = anc[v][i];
return fa[u];
} int bsearch(int u, int v, int l, int x) {
int L = 0, R = M, cnt = 0, sum = 0;
while(L < R) {
int mid = (L + R) / 2;
int tcnt = T[T[u].lch].cnt + T[T[v].lch].cnt - T[T[l].lch].cnt * 2;
int tsum = T[T[u].lch].sum + T[T[v].lch].sum - T[T[l].lch].sum * 2;
if((cnt + tcnt) * mid - tsum - sum > x) {
u = T[u].lch, v = T[v].lch, l = T[l].lch;
R = mid;
} else {
cnt += tcnt; sum += tsum;
u = T[u].rch, v = T[v].rch, l = T[l].rch;
L = mid + 1;
}
}
return L - 1;
} int main()
{
int _; scanf("%d", &_);
for(int kase = 1; kase <= _; kase++) {
printf("Case #%d:\n", kase); scanf("%d%d", &n, &m); sz = 0;
ecnt = 0;
memset(head, -1, sizeof(head));
for(int i = 1; i < n; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
AddEdge(u, v, w); AddEdge(v, u, w);
} dfs(1); preprocess();
while(m--) {
int u, v, k, a, b;
scanf("%d%d%d%d%d", &u, &v, &k, &a, &b);
int lca = LCA(u, v);
int base = query(root[u], root[v], root[lca], 0, M, 1);
if(a <= b) printf("%d\n", base + k / a);
else {
int ans = base;
if(k >= a) ans += (k - a) / b + 1;
int x = k / b;
ans = max(ans, bsearch(root[u], root[v], root[lca], x));
printf("%d\n", ans);
}
}
} return 0;
}

HDU 4729 An Easy Problem for Elfness 主席树的更多相关文章

  1. HDU 4729 An Easy Problem for Elfness(树链剖分边权+二分)

    题意 链接:https://cn.vjudge.net/problem/HDU-4729 给你n个点,然你求两个点s和t之间的最大流.而且你有一定的钱k,可以进行两种操作 1.在任意连个点之间建立一个 ...

  2. 数据结构(主席树):HDU 4729 An Easy Problem for Elfness

    An Easy Problem for Elfness Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (J ...

  3. HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一个带边权的图.对于每一个询问(S , ...

  4. HDU 4729 An Easy Problem for Elfness(主席树)(2013 ACM/ICPC Asia Regional Chengdu Online)

    Problem Description Pfctgeorge is totally a tall rich and handsome guy. He plans to build a huge wat ...

  5. 【HDOJ】4729 An Easy Problem for Elfness

    其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到 ...

  6. hdu 5475 An easy problem(暴力 || 线段树区间单点更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=5475 An easy problem Time Limit: 8000/5000 MS (Java/Others ...

  7. [HDU4729]An Easy Problem for Elfness

    [HDU4729]An Easy Problem for Elfness 题目大意: 给你一棵\(n(n\le10^5)\)个点的树,树上每条边都有容量. \(m(m\le10^5)\)次询问,每次询 ...

  8. HDU 5475 An easy problem 线段树

    An easy problem Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. HDU 2132 An easy problem

    http://acm.hdu.edu.cn/showproblem.php?pid=2132 Problem Description We once did a lot of recursional ...

随机推荐

  1. js之深度克隆、简易克隆

    一.js中的对象 谈到对象的克隆,必定要说一下对象的概念. js中的数据类型分为两大类:原始类型和对象类型. (1)原始类型包括:数值.字符串.布尔值.null.undefined(后两个是特殊的原始 ...

  2. Android 贝塞尔曲线的浅析

    博客也开了挺长时间了,一直都没有来写博客,主要原因是自己懒---此篇博客算是给2017年一个好的开始,同时也给2016年画上一个句点,不留遗憾. 那就让我们正式进入今天的主题:贝塞尔曲线. 首先,让我 ...

  3. 《spss统计分析与行业应用案例详解》:实例九 单一样本t检验

    单一样本t检验的功能与意义 spss的单一样本t检验过程是瑕设检验中最基本也是最常用的方法之一,跟所有的假没检验一样,其依剧的基木原理也是统计学中的‘小概率反证法”原理.通过单一样本t检验.我们可以实 ...

  4. 以后要进行数据收集,打开邮箱就行了 | formtalk入驻Office 应用商店

    『数据收集』,作为一项工作,存在感高的忽视不了——不管你在企业里是什么角色(大部分),Ta似乎都在你的工作范围内. 你是人事:收集招聘数据.员工信息: 你是采购:收集供应商信息.商品数据: 你是市场: ...

  5. 打印机 Microsoft Print to PDF 所需的驱动程序 Microsoft Print To PDF 未知。登录之前,请与管理员联系,安装驱动程序。

    这个问题发生后,我觉得很疑惑,因为服务器上确定没有安装打印机.那么打印机是从哪里来的呢? 通过百度搜索,发现网上的一个帖子解答了我的疑惑.原帖地址:http://blog.chinaunix.net/ ...

  6. ZOJ 3469 Food Delivery (区间DP,经典)

    题意: 在x轴上有一家外卖餐馆,有n个顾客站在x轴上不同坐标上且叫了外卖,每个人的脾气不同,每1分钟没有收到外卖就会增加Fi点愤怒值,而外卖小哥的车是有速度的v-1/分钟,问怎样的送餐次序会让所有顾客 ...

  7. 远程桌面连接(mstsc)无法断开的解决方案

    某2008 r2有二个系统账户,同时允许两个tcp连接,但每个用户仅同时允许一人登录.不知何因,关闭远程桌面连接的窗口后,再次连接就瞬间提示无法被连接.查看了事件查看器,信息为被注销,这是因为设置了“ ...

  8. Linux中根据访问日志统计访问量最高的前N个IP

    前段时间面试中被问到如上问题,日常不怎么注意积累,以此谨记. 访问IP 页面[nxuser@im440-zh test]$ vi log 135.252.172.181 page1 136.252.1 ...

  9. Spark集群任务提交

    1. 集群管理器 Spark当前支持三种集群管理方式 Standalone—Spark自带的一种集群管理方式,易于构建集群. Apache Mesos—通用的集群管理,可以在其上运行Hadoop Ma ...

  10. Tomcat详细安装配置

    1.首先是Tomcat的获取和安装. 获取当然得上Apache的官方网站下载,开源免费,而且带宽也足够.下载会很快. 这是两种不同的下载,一个是普通安装版本,一个是解压安装版本.使用起来是一样的,只是 ...