[HDU4729]An Easy Problem for Elfness

题目大意:

给你一棵\(n(n\le10^5)\)个点的树,树上每条边都有容量。

\(m(m\le10^5)\)次询问,每次询问你有\(k\)的预算,可以花\(a\)的代价在任意两点间建一条流容量为\(1\)的边(包括重边),或者花费\(b\)的代价将某条边的容量加\(1\),问在不超过预算的情况下,从\(s\)到\(t\)的最大流量。

思路:

首先,考虑没有\(k,a,b\)的情况,答案就是\(s,t\)路径上的权值最小值\(min\)。

对于\(a\le b\)的情况,由于我们每在\(s\)和\(t\)之间新建一条边都能增加\(1\)的容量,则我们把所有的预算都用来新建边肯定是最优策略。答案是\(min+\lfloor\frac ka\rfloor\)。

对于\(a>b\)的情况,我们有以下两种可能最优的策略:

  1. 花费\(a\)的代价新建一条边,然后用剩下的所有预算扩充这条新边的容量。
  2. 不断将路径上最小边扩充\(1\)的容量。

对于第一种策略,我们不难得到答案就是\(min+1+\lfloor\frac{k-a}b\rfloor\)。

对于第二种策略,我们可以二分答案\(mid\)。设路径上边容量\(<mid\)的边数有\(c\)个,权值和为\(w\)。则\(c\times mid-w\)就是需要扩充的容量之和。若\(c\times mid-w\le\lfloor\frac kb\rfloor\),则\(ans>=mid\),反之\(ans<mid\)。

上文提及的边数与权值和可以用树上主席树方便地求得。

时间复杂度\(\mathcal O(n\log^2n)\)。

源代码:

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<climits>
  4. #include<algorithm>
  5. #include<forward_list>
  6. inline int getint() {
  7. register char ch;
  8. while(!isdigit(ch=getchar()));
  9. register int x=ch^'0';
  10. while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
  11. return x;
  12. }
  13. using int64=long long;
  14. constexpr int N=1e5+1,logN=17,logW=15,W=10000;
  15. using Edge=std::pair<int,int>;
  16. std::forward_list<Edge> e[N];
  17. inline void add_edge(const int &u,const int &v,const int &w) {
  18. e[u].emplace_front((Edge){v,w});
  19. e[v].emplace_front((Edge){u,w});
  20. }
  21. int n,m,s,t,k,a,b;
  22. class FotileTree {
  23. #define mid ((b+e)>>1)
  24. private:
  25. struct Node {
  26. int sum;
  27. int64 val;
  28. int left,right;
  29. std::pair<int,int64> operator + (const Node &rhs) const {
  30. return std::make_pair(sum+rhs.sum,val+rhs.val);
  31. }
  32. friend std::pair<int,int64> operator - (const std::pair<int,int64> &lhs,const Node &rhs) {
  33. return std::make_pair(lhs.first-rhs.sum,lhs.second-rhs.val);
  34. }
  35. Node operator * (const int &rhs) const {
  36. return {sum*rhs,val*rhs};
  37. }
  38. };
  39. Node node[N*logW];
  40. int sz,new_node(const int &p) {
  41. node[++sz]=node[p];
  42. return sz;
  43. }
  44. public:
  45. int root[N];
  46. void reset() {
  47. sz=0;
  48. }
  49. void insert(int &p,const int &b,const int &e,const int &x) {
  50. p=new_node(p);
  51. node[p].sum++;
  52. node[p].val+=x;
  53. if(b==e) return;
  54. if(x<=mid) insert(node[p].left,b,mid,x);
  55. if(x>mid) insert(node[p].right,mid+1,e,x);
  56. }
  57. std::pair<int,int64> query(const int &p,const int &q,const int &r,const int &b,const int &e,const int64 &x) const {
  58. if(node[p]+node[q]-node[r]*2==std::make_pair(0,0ll)) return std::make_pair(0,0);
  59. if(x>=e) return node[p]+node[q]-node[r]*2;
  60. if(x<=mid) {
  61. return query(node[p].left,node[q].left,node[r].left,b,mid,x);
  62. } else {
  63. const auto p1=query(node[p].left,node[q].left,node[r].left,b,mid,x);
  64. const auto p2=query(node[p].right,node[q].right,node[r].right,mid+1,e,x);
  65. return std::make_pair(p1.first+p2.first,p1.second+p2.second);
  66. }
  67. }
  68. #undef mid
  69. };
  70. FotileTree tr;
  71. void reset() {
  72. for(register int i=1;i<=n;i++) e[i].clear();
  73. tr.reset();
  74. }
  75. inline int lg2(const float &x) {
  76. return ((unsigned&)x>>23&255)-127;
  77. }
  78. int anc[N][logN],min[N][logN]={{INT_MAX}},dep[N];
  79. void dfs(const int &x,const int &par) {
  80. anc[x][0]=par;
  81. dep[x]=dep[par]+1;
  82. for(register int i=1;i<=lg2(dep[x]);i++) {
  83. anc[x][i]=anc[anc[x][i-1]][i-1];
  84. min[x][i]=std::min(min[x][i-1],min[anc[x][i-1]][i-1]);
  85. }
  86. for(auto &i:e[x]) {
  87. const int &y=i.first,&w=i.second;
  88. if(y==par) continue;
  89. tr.insert(tr.root[y]=tr.root[x],0,W,min[y][0]=w);
  90. dfs(y,x);
  91. }
  92. }
  93. int get_min(int x,int y) {
  94. if(dep[x]<dep[y]) std::swap(x,y);
  95. int ret=INT_MAX;
  96. for(register int i=lg2(dep[x]-dep[y]);i>=0;i--) {
  97. if(dep[anc[x][i]]>=dep[y]) {
  98. ret=std::min(ret,min[x][i]);
  99. x=anc[x][i];
  100. }
  101. }
  102. if(x==y) return ret;
  103. for(register int i=lg2(dep[x]);i>=0;i--) {
  104. if(anc[x][i]!=anc[y][i]) {
  105. ret=std::min(ret,min[x][i]);
  106. ret=std::min(ret,min[y][i]);
  107. x=anc[x][i];
  108. y=anc[y][i];
  109. }
  110. }
  111. ret=std::min(ret,min[x][0]);
  112. ret=std::min(ret,min[y][0]);
  113. return ret;
  114. }
  115. inline int get_lca(int x,int y) {
  116. if(dep[x]<dep[y]) std::swap(x,y);
  117. for(register int i=lg2(dep[x]-dep[y]);i>=0;i--) {
  118. if(dep[anc[x][i]]>=dep[y]) {
  119. x=anc[x][i];
  120. }
  121. }
  122. if(x==y) return x;
  123. for(register int i=lg2(dep[x]);i>=0;i--) {
  124. if(anc[x][i]!=anc[y][i]) {
  125. x=anc[x][i];
  126. y=anc[y][i];
  127. }
  128. }
  129. return anc[x][0];
  130. }
  131. inline bool check(const int64 &mid) {
  132. const auto tmp=tr.query(tr.root[s],tr.root[t],tr.root[get_lca(s,t)],0,W,mid);
  133. return tmp.first*mid-tmp.second<=k/b;
  134. }
  135. int main() {
  136. const int T=getint();
  137. for(register int i=1;i<=T;i++) {
  138. printf("Case #%d:\n",i);
  139. n=getint(),m=getint();
  140. for(register int i=1;i<n;i++) {
  141. const int u=getint(),v=getint(),w=getint();
  142. add_edge(u,v,w);
  143. }
  144. dfs(1,0);
  145. for(register int i=0;i<m;i++) {
  146. s=getint(),t=getint(),k=getint(),a=getint(),b=getint();
  147. const int min=get_min(s,t);
  148. if(a<=b) {
  149. printf("%lld\n",min+(int64)k/a);
  150. continue;
  151. }
  152. int64 l=min+(int64)k/a+1,r=min+(int64)k/b;
  153. while(l<=r) {
  154. const int64 mid=(l+r)>>1;
  155. if(check(mid)) {
  156. l=mid+1;
  157. } else {
  158. r=mid-1;
  159. }
  160. }
  161. printf("%lld\n",k>=a?std::max(min+1+(int64)(k-a)/b,l-1):l-1);
  162. }
  163. reset();
  164. }
  165. return 0;
  166. }

[HDU4729]An Easy Problem for Elfness的更多相关文章

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

  2. 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 ...

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

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

  4. 【HDOJ】4729 An Easy Problem for Elfness

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

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

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

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

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

  7. UVA-11991 Easy Problem from Rujia Liu?

    Problem E Easy Problem from Rujia Liu? Though Rujia Liu usually sets hard problems for contests (for ...

  8. An easy problem

    An easy problem Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Sub ...

  9. UVa 11991:Easy Problem from Rujia Liu?(STL练习,map+vector)

    Easy Problem from Rujia Liu? Though Rujia Liu usually sets hard problems for contests (for example, ...

随机推荐

  1. 八大疯狂的HTML5 Canvas及WebGL动画效果——8 CRAZY ANIMATIONS WITH WEBGL AND HTML5 CANVAS【收藏】

    HTML5, WebGL and Javascript have changed the way animation used to be. Past few years, we can only a ...

  2. HTML -- get与post提交方式的区别 -- (转)

    在写代码过程中,get与post是两种不同的提交方式.下面,列举出两种方式的不同. 方法/步骤   get是从服务器上获取数据,post是向服务器传送数据.   get是把参数数据队列加到提交表单的A ...

  3. Eureka服务续约(Renew)源码分析

    主要对Eureka的Renew(服务续约),从服务提供者发起续约请求开始分析,通过阅读源码和画时序图的方式,展示Eureka服务续约的整个生命周期.服务续约主要是把服务续约的信息更新到自身的Eurek ...

  4. html meta标签作用

    1.概要 标签提供关于HTML文档的元数据.元数据不会显示在页面上,但是对于机器是可读的.它可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他web服务. 必要属性: conten ...

  5. xcode 配置系统环境变量 Preporocessing 预编译宏的另一种写法, 系统的DEBUG 由来

    在某些项目中看到一些环境变量类似宏的东西 比如叫ENVIRONMENT, 但发现还找不到具体这个宏是什么值, 那是因为他实在Preprocessing里配置了这个宏的值, 他能配置debug/rele ...

  6. java的装饰设计模式

    类似python中的装饰器. 示例: public class Test5 { public static void main(String[] args) { Worker w = new Work ...

  7. java中的i++与++i有什么区别?

    刚开始接触时,做了一些小测试,还以为这两个没有什么区别. public class OperatorDemo { public static void main(String[] args){ int ...

  8. linux命令(13):kill/killall命令

    停止指定的进程名:kill 进程ID号 把所有httpd进程杀掉:killall httpd 强制停止进程mysqld:killall -9 mysqld

  9. LeetCode239. Sliding Window Maximum

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

  10. hdu5731

    先求出不考虑分割线的n*m棋盘的覆盖方案数记为f[n][m] 然后枚举列分割线的状态(状压),计算此时不存在行分割线的方案数 求出这个我们就可以用容斥原理算出答案了 怎么算在列分割线确定的情况下,不存 ...