转载请注明出处,谢谢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. lostash 正则

     (?:\s+?)  0个或者多个空格

  2. linux 命令总结(转载)

    linux 命令总结(转载) 1. 永久更改ip ifconfig eth0 新ip 然后编辑/etc/sysconfig/network-scripts/ifcfg-eth0,修改ip 2.从Lin ...

  3. intro

    懒得自己折腾wordpress又很想写博客. 作为一名把自己当成programmer的data scientist,毅然选择了博客园. 这里我想内容就是平时学到/使用的各种心得,更新频率不定. 兴趣范 ...

  4. nyoj 43 24 Point game(dfs暴力)

    描述 There Point game. In .The expression mustn't have any other operator except plus,minus,multiply,d ...

  5. MapReduce TotalOrderPartitioner 全局排序

    我们知道Mapreduce框架在feed数据给reducer之前会对map output key排序,这种排序机制保证了每一个reducer局部有序,hadoop 默认的partitioner是Has ...

  6. java中substring的使用方法

    java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...

  7. PipedInputStream/PipedOutputStream原理

    PipedInputStream类与PipedOutputStream类用于在应用程序中创建管道通信.一个PipedInputStream实例对象必须和一个PipedOutputStream实例对象进 ...

  8. asp.net application

    Application 对象用于存储和访问来自任何页面的变量,类似于 session 对象.不同之处在于,所有的用户分享一个 Application 对象,而 session 对象和用户的关系是一一对 ...

  9. chrome浏览器的桌面通知

    最近在使用朋友网(不加链接,避免有打广告的嫌疑),发现会出现提示“是否允许网站显示桌面通知?”,如下图所示: 这种做法,在页面加载完时直接调用请求,比起开心网的这种提示感觉有些野蛮了.开心网的桌面通知 ...

  10. Apache 日志配置,包含过滤配置

    最近排查支付宝交易成功后异步通知执行失败的原因,需要查看Apache的日志,发现之前一直没对日志进行设置,结果日志文件都1.5G多了,于是搜索了如何按天记录日志. 但公司的网站是通过阿里云的SLB分发 ...