转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意:给出一个带边权的图。对于每一个询问(S , T , K , A , B),有两种操作,加一条单位边花费为A,将某条边流量扩展一个单位花费为B,在预算为K的情况下求S到T最大流的最大值。

http://acm.hdu.edu.cn/showproblem.php?pid=4729

做法:如果A <= B,很明显只做添加边操作,而且只加在S - T之间,加一条边流量加1。所以结果是初始流量 + K / A。

如果A > B,则有两种可能,要进行添加边操作,这样的话,显然只添加一条边,就是S - T,然后 不断扩展这条边,那么结果就是初始流量 + K >= A ? 1 : 0 + max (0 , (K - A) / B)。

否则的话,便是只进行扩展操作。

第一个问题:怎么求出初始流量,显然是路径中边权最小的值,问题转化为树上第K大,主席树可以解决 。

第二个问题:只进行扩展操作。显然可以二分,然后判断路径中边权小于这个值的和,以及个数。就能算出花费。但是这样貌似会超时,可以直接在线段树进行逼近。差不多就是用线段树完成二分操作,算出可以增加到的最大限度。

第一次写的时候是按流量离散化了。。。。然后 发现在第二个问题是不方便实现。。。离散化之后不好统计。然后 发现流量只有1W,就直接建树了。。。连续情况下就考虑了所有情况。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#define lowbit(x) (x & (-x))
#define Key_value ch[ch[root][1]][0]
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long LL;
const int N = 110005;
const int M = 2000000;
struct Edge {
int v , w , next;
}edge[N << 1];
int n , q;
int start[N] , tot;
void _add (int u , int v , int w) {
edge[tot].v = v;
edge[tot].w = w;
edge[tot].next = start[u];
start[u] = tot ++;
}
void add (int u , int v , int w) {
_add (u , v , w);
_add (v , u , w);
}
int depth , b[N << 1] , cnt , p[N] , f[N];
int x[N] , m;
int T[M] , num[M] , sum[M] , nodecnt , lson[M] , rson[M];
void Init_hash () {
sort (x , x + n - 1);
m = unique (x , x + n - 1) - x;
}
int hash (int y) {
return y;
return lower_bound (x , x + m , y) - x + 1;
}
int bulid (int l , int r) {
int root = nodecnt ++;
num[root] = 0;
sum[root] = 0;
if (l != r) {
int mid = (l + r) >> 1;
lson[root] = bulid (l , mid);
rson[root] = bulid (mid + 1 , r);
}
return root;
}
int update (int root , int l , int r , int pos , int val) {
int newroot = nodecnt ++;
num[newroot] = num[root] + 1;
sum[newroot] = sum[root] + val;
if (l != r) {
int mid = (l + r) >> 1;
if (pos <= mid) {
lson[newroot] = update (lson[root] , l , mid , pos , val);
rson[newroot] = rson[root];
}
else {
rson[newroot] = update (rson[root] , mid + 1 , r , pos , val);
lson[newroot] = lson[root];
}
}
return newroot;
}
// search kth
int query (int left_root , int right_root , int lca_root , int l , int r , int k) {
if (l == r) return l;
int cal = num[lson[left_root]] + num[lson[right_root]] - 2 * num[lson[lca_root]];
int mid = (l + r) >> 1;
if (cal >= k)
return query (lson[left_root] , lson[right_root] , lson[lca_root] , l , mid , k);
else
return query (rson[left_root] , rson[right_root] , rson[lca_root] , mid + 1 , r , k - cal);
}
int query (int left_root , int right_root , int lca_root , int k) {
int calcnt = num[left_root] + num[right_root] - 2 * num[lca_root];
int l = 1 , r = m;
int nowcnt = 0 , nowsum = 0;
while (l < r) {
int tmpcnt = num[lson[left_root]] + num[lson[right_root]] - 2 * num[lson[lca_root]];
int tmpsum = sum[lson[left_root]] + sum[lson[right_root]] - 2 * sum[lson[lca_root]];
int mid = (l + r) >> 1;
if (mid * (tmpcnt + nowcnt) - tmpsum - nowsum >= k) {
r = mid;
left_root = lson[left_root];right_root = lson[right_root];lca_root = lson[lca_root];
}
else {
l = mid + 1;
nowcnt += tmpcnt;nowsum += tmpsum;
left_root = rson[left_root];right_root = rson[right_root];lca_root = rson[lca_root];
}
}
if (k - (nowcnt * l - nowsum) < 0) l --;
return l + (k - (nowcnt * l - nowsum)) / calcnt;
}
void dfs(int u , int pre){
int t = ++ depth;
b[++ cnt] = t;
f[t] = u;
p[u] = cnt;
for(int i = start[u] ; i != -1 ; i = edge[i].next){
int v = edge[i].v , w = edge[i].w;
if (v == pre) continue;
T[v] = update (T[u] , 1 , m , hash(w) , w);
dfs (v , u);
b[++ cnt] = t;
}
}
int dp[N << 1][20];
void Init_rmq(int n){
for(int i = 1 ; i <= n ; i++)
dp[i][0] = b[i];
int m = floor (log (n * 1.0) / log (2.0));
for (int j = 1 ; j <= m ; j ++)
for (int i = 1;i <= n - (1 << j) + 1 ; i ++)
dp[i][j] = min (dp[i][j - 1] , dp[i + (1 << (j - 1))][j - 1]);
}
int rmq (int l , int r){
int k = floor (log ((r - l + 1) * 1.0) / log (2.0));
return min (dp[l][k] , dp[r - (1 << k) + 1][k]);
}
int lca (int a , int b){
if (p[a] > p[b]) swap(a , b);
return f[rmq (p[a] , p[b])];
} int main () {
#ifndef ONLINE_JUDGE
freopen ("input.txt" , "r" , stdin);
// freopen ("output.txt" , "w" , stdout);
#endif
int t , cas = 0;
scanf ("%d" , &t);
while (t --) {
tot = depth = cnt = nodecnt = 0;
memset (start , -1 , sizeof(start));
scanf ("%d %d" , &n , &q);
for (int i = 1 ; i < n ; i ++) {
int u , v , w;
scanf ("%d %d %d" , &u , &v , &w);
add (u , v , w + 1);
x[i - 1] = w;
}
// Init_hash ();
m = 10000;
T[1] = bulid (1 , m);
dfs (1 , 0);
Init_rmq (cnt);
printf ("Case #%d:\n" , ++cas);
while (q --) {
int s , e , k , a , b;
scanf ("%d %d %d %d %d" , &s , &e , &k , &a , &b);
int initial = query (T[s] , T[e] , T[lca (s , e)] , 1 , m , 1);
if (a <= b) printf ("%d\n" , initial + k / a - 1);
else {
int ans = initial;
if (k >= a) ans = ans + 1 + (k - a) / b;
int ret = query (T[s] , T[e] , T[lca (s , e)] , k / b);
// cout << initial << " " << ans << " " << ret << endl;
printf ("%d\n" , max (ans , ret) - 1);
}
}
}
return 0;
}

HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)的更多相关文章

  1. HDU 4729 An Easy Problem for Elfness 主席树

    题意: 给出一棵树,每条边有一个容量. 有若干次询问:\(S \, T \, K \, A \, B\),求路径\(S \to T\)的最大流量. 有两种方法可以增大流量: 花费\(A\)可以新修一条 ...

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

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

  3. 数据结构(主席树):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 ...

  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. HDU 6278 主席树(区间第k大)+二分

    Just h-index Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)To ...

  8. POJ 2104 K-th Number 主席树(区间第k大)

    题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...

  9. POJ 2104:K-th Number(主席树静态区间k大)

    题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...

随机推荐

  1. QT5中如何使用QFtp类(这个类虽然没有被收录,但一直在更新)

    由于QT5对QML的支持有很大的改进,所以打算将原来基于QT4的程序移植到QT5上,在移植用QFtp类写的程序时傻眼了! Qt5 移除了 QFtp API,原因是其实现质量.QNetworkAcces ...

  2. JDBC批量操作

    /**          * 批量执行预定义模式的SQL          */         public static void exeBatchParparedSQL() {          ...

  3. codevs2822 爱在心中

      2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无 ...

  4. 【FSFA 读书笔记】Ch 2 Computer Foundatinons(2)

    Hard Disk Technology 1. 机械硬盘内部构造 几个重要概念:Sector(扇区),Head(读写头),Track(磁道),Cylinder(柱面). 如果一个文件比较大,磁盘的写入 ...

  5. [置顶] Direct UI

    有个坑爹的说法:其实Direct UI只是一个思想,要实现这个思想,还要靠自己. 采用windowless方式用api或gdi实现ui的绘制. DirectUI意为直接在父窗口上绘图(Paint on ...

  6. java的静态代理

    解决这个问题:在多个模块要插入一段功能,比方,在不同业务处理模块中,都须要检查用户是否登录,假设不使用代理的话,每添加一个模块,就须要添加非常多代码. 比方,除了推断是否登录,假设还须要添加一个记录日 ...

  7. 傅老师课堂:Java高级应用之Struts2+Spring2+Hibernate3大集成

    开篇一笑:一对情侣,非常恩爱,但男友喜欢说脏话,一天女友提出要带男友回家吃个饭,见见家长,千叮万嘱让男友别说脏话,男友在家憋了一晚上没说一句脏话,天气寒冷,到走的时候女友家长要出来送他们,男友客气的说 ...

  8. (转)c#对象内存模型

    对象内存模型 C#的对象内存模型写这篇博客的主要目的是为了加深自己的理解,如有不对的地方,请各位见谅. C#的对象内存模型: 一.栈内存和堆内存1.栈内存 由编译器自动分配和释放,主要用来保存一些局部 ...

  9. DSOframer 的简单介绍和资源整理

    DSOframer 是微软提供一款开源的用于在线编辑 Word. Excel .PowerPoint 的 ActiveX 控件.国内很多著名的 OA 中间件,电子印章,签名留痕等大多数是依此改进而来的 ...

  10. js写的复制功能,只支持IE

    如果用js写,只能支持IE,如果想全支持,需要用jQuery的插件:jquery.zclip.js 下面是用js写的: var copyHref = function(){               ...