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

An Easy Problem for Elfness

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1148    Accepted Submission(s): 234

Problem Description

Pfctgeorge
is totally a tall rich and handsome guy. He plans to build a huge water
transmission network that covers the whole southwest China. To save the
fund, there will be exactly one path between two cities.

Since
the water every city provides and costs every day is different, he needs
to transfer water from one particular city to another as much as
possible in the next few days. However the pipes which connect the
cities have a limited capacity for transmission. (Which means the water
that transfer though the pipe should not exceed a particular amount) So
he has to know the maximum water that the network can transfer in the
next few days.

He thought it‘s a maximum flow problem, so he
invites an expert in this field, Elfness (Also known as Xinhang senior
sister) to help him figure it out.

Unlike Pfctgeorge, Elfness
quickly finds that this problem is much easier than a normal maximum
flow problem, and is willing to help Pfctgeorge.

"Oh well, this problem is not a tough one. We can ..."

Abruptly, Pfctgeorge‘s iPhone rings, and ... the ringtone is Mo Di Da Biao Ke.

"You can make that? Excellent! "Pfctgeorge hangs up his iPhone, and turns to Elfness.

"Here‘s
good news for you. A construction team told me that every pipe‘s
capacity can be extended for one day. And the price for extending one
unit capacity varies from day to day. "

"Eh well, that‘s a good
news for you, not me. Now it‘s rather like a minimum cost ow problem,
right? But it‘s still not a tough one, let me have a think. "

After a few seconds‘ thought, Elfness comes up with a simple solution.

"Ok, we can solve it like... "

Abruptly, here comes Mo Di Da Biao Ke again.

"Seriously? You can build new pipes? Thank you very much. "

"OK,
my dear Elfness, we got more good news. Another construction team said
they can build one or more pipes between any two cities and their pipes
are exactly like the original ones except that they only work for one
day. And the capacity of the new pipes is only one, but they can be
extended, too. Of course, their price to build a single pipe also varies
in days. "

"You mean the new pipes can be extended too? Wow, things are getting more interesting. Give me a few minutes. "

Elfness takes out his new ultrabook which is awarded in VK cup and does some basic calculation.

"I get it. The problem can be solved ..."

Mo Di Da Biao Ke again, but this time it‘s from Elfness‘s phone.

"As you see, I have to go out. But I know someone else who can also solve this; I‘ll recommend this guy for you. "

And
of course, that poor guy is YOU. Help Pfctgeorge solve his problem, and
then the favorability about you from Elfness will raise a lot.

Input

The first line has a number T (T <= 10) , indicating the number of test cases.

The
first line of each test case is two integers N (1 <= N <= 100000)
and M (1 <= M <= 100000), indicating the number of the city that
the original network connects and the number of days when Pfctgeorge
needs to know about the maximum water transmissions. Then next N - 1
lines each describe a pipe that connects two cities. The format will be
like U, V , cap (1 <= U, V <= N and 0 <= cap < 10000), which
means the ids of the two cities the pipe connects and the transmission
limit of the pipe. As is said in description, the network that the
cities and pipes form is a tree (an undirected acyclic graph).

Then next M lines of the test case describe the information about the next few days. The format is like S, T, K, A, B(0 <= K <= 2^31 - 1, 1 <= A, B <= 2^31 - 1).
S means the source of the water while T means the sink. K means the
total budget in the day. A means the cost for a construction team to
build a new pipe and B means the cost for a construction team to extend
the capacity of a pipe.

I am glad to list the information of building a new pipe and extending the capacity.

1.
Pfctgeorge can build a new pipe between any two cities, no matter they
have been directly connected or not. Pfctgeorge can build more than one
new pipe between any two cities.
2. The capacity of the pipe that was newly built is one.
3. Pfctgeorge can extend the capacity of any existed pipe including the newly built one and the original one.
4. Each time you extend the capacity of one pipe, the capacity of that pipe increases one.
5. The cost of building a new pipe is A and the cost of extending a pipe is B.
6. You can take any constructions in any times and the only limit is to make sure the total costs not exceed the budget.
7. All the work that construction team does only lasts one single day.

Output

For every case, you should output "Case #t:" at first, without quotes. The t is the case number starting from 1.
Then for each day, output the maximum water Pfctgeorge can transfer from S and T with a budget of K.

Sample Input

2
5 1
1 2 2
1 3 5
2 4 1
4 5 2
1 5 3 3 2
5 5
1 2 10
2 3 2
3 4 7
2 5 7
1 5 0 1 3
1 3 0 2 3
1 5 3 2 3
1 2 7 3 1
1 3 2 3 1

Sample Output

Case #1:
2
Case #2:
7
2
8
17
4

Hint

In the first sample case, you can extend the capacity of the pipe which connects city2 and city4 by one, or just build a new pipe between city2 and city4.

  感觉这道题就是一个笑话。

  本地对拍会爆,但HDU上AC了……

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=100010;
  6 #pragma comment(linker,"/STACK:1024000000,1024000000")
  7 int cntE,fir[maxn],to[maxn*2],nxt[maxn*2],cap[maxn*2];
  8 int rt[maxn],ch[maxn*15][2],sum[maxn*15],cal[maxn*15],cnt;
  9 int dep[maxn];
 10 int max(int a,int b){return a>b?a:b;}
 11 void addedge(int a,int b,int c){
 12     nxt[++cntE]=fir[a];
 13     fir[a]=cntE;
 14     cap[cntE]=c;
 15     to[cntE]=b;
 16 }
 17
 18 void Insert(int pre,int &rt,int l,int r,int g){
 19     rt=++cnt;
 20     ch[rt][0]=ch[pre][0];
 21     ch[rt][1]=ch[pre][1];
 22     sum[rt]=sum[pre]+1;
 23     cal[rt]=cal[pre]+r-g+1;
 24     if(l==r)return;
 25     int mid=(l+r)>>1;
 26     if(mid>=g)Insert(ch[pre][0],ch[rt][0],l,mid,g);
 27     else Insert(ch[pre][1],ch[rt][1],mid+1,r,g);
 28 }
 29
 30 int ID[maxn],tot;
 31 int mm[maxn*3],Min[maxn*3][20];
 32
 33 void DFS(int x,int fa){
 34     Min[ID[x]=++tot][0]=x;
 35     for(int i=fir[x];i;i=nxt[i])
 36         if(to[i]!=fa){
 37             dep[to[i]]=dep[x]+1;
 38             Insert(rt[x],rt[to[i]],0,9999,cap[i]);
 39             DFS(to[i],x);Min[++tot][0]=x;
 40         }
 41 }
 42
 43 void Prepare(){
 44     for(int i=1;i<=tot;i++){
 45         if((i&(i-1))==0)mm[i]=mm[i-1]+1;
 46         else mm[i]=mm[i-1];
 47     }
 48     for(int k=1;k<=mm[tot];k++)
 49         for(int i=1;i+(1<<k)-1<=tot;i++){
 50             if(dep[Min[i][k-1]]<dep[Min[i+(1<<k-1)][k-1]])
 51                 Min[i][k]=Min[i][k-1];
 52             else
 53                 Min[i][k]=Min[i+(1<<k-1)][k-1];
 54         }
 55 }
 56
 57 int Lca(int x,int y){
 58     if(ID[x]>ID[y])swap(x,y);
 59     int k=mm[ID[y]-ID[x]+1];
 60     if(dep[Min[ID[x]][k]]<dep[Min[ID[y]-(1<<k)+1][k]])
 61         return Min[ID[x]][k];
 62     return Min[ID[y]-(1<<k)+1][k];
 63 }
 64
 65 #define num() sum[ch[r1][0]]+sum[ch[r2][0]]-2*sum[ch[lca][0]]
 66 #define key() cal[ch[r1][0]]+cal[ch[r2][0]]-2*cal[ch[lca][0]]
 67
 68 int Query1(int lca,int r1,int r2,int l,int r){
 69     if(l==r)return l;
 70     int mid=(l+r)>>1;
 71     if(num()>0)
 72     return Query1(ch[lca][0],ch[r1][0],ch[r2][0],l,mid);
 73     return Query1(ch[lca][1],ch[r1][1],ch[r2][1],mid+1,r);
 74 }
 75
 76
 77 int Query2(int lca,int r1,int r2,int l,int r,int k,int t){
 78     if(l==r)return l;
 79     int mid=(l+r)>>1,tmp;
 80     tmp=key()+t*(mid-l+1);
 81     if(tmp>k)return Query2(ch[lca][0],ch[r1][0],ch[r2][0],l,mid,k,t);
 82     return Query2(ch[lca][1],ch[r1][1],ch[r2][1],mid+1,r,k-tmp,t+num());
 83 }
 84
 85 int T,n,Q,cas;
 86 int s,t,k,a,b,ans;
 87 void Init(){
 88     printf("Case #%d:\n",++cas);
 89     memset(sum,0,sizeof(sum));
 90     memset(cal,0,sizeof(cal));
 91     memset(fir,0,sizeof(fir));
 92     memset(Min,0,sizeof(Min));
 93     mm[0]=-1;cntE=cnt=tot=0;
 94 }
 95
 96 int main(){
 97     scanf("%d",&T);
 98     while(T--){
 99         Init();
100         scanf("%d%d",&n,&Q);
101         for(int i=1,c;i<n;i++){
102             scanf("%d%d%d",&a,&b,&c);
103             addedge(a,b,c);
104             addedge(b,a,c);
105         }
106
107         DFS(1,0);
108         Prepare();
109
110         while(Q--){
111             scanf("%d%d",&s,&t);
112             scanf("%d%d%d",&k,&a,&b);
113             int lca=Lca(s,t),tmp;
114             tmp=Query1(rt[lca],rt[s],rt[t],0,9999);
115             if(a<=b)
116                 ans=tmp+k/a;
117             else{
118                 ans=tmp;
119                 if(k>=a)ans+=1+(k-a)/b;
120                 ans=max(ans,Query2(rt[lca],rt[s],rt[t],0,9999,k/b,0));
121             }
122             printf("%d\n",ans);
123         }
124     }
125     return 0;
126 }
时间: 2024-09-30 11:56:53

数据结构(主席树):HDU 4729 An Easy Problem for Elfness的相关文章

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

题意 链接:https://cn.vjudge.net/problem/HDU-4729 给你n个点,然你求两个点s和t之间的最大流.而且你有一定的钱k,可以进行两种操作 1.在任意连个点之间建立一个单位1的流,费用a 2.将原先的流扩大1个单位,费用b 思路 题目已经说了是一棵树,那么树上两点的最大流就是两点路径上的最小值.其实两种操作各一次对最大流的贡献是相等的.我们分类讨论: 如果a<=b,直接算第一种方案即可,直接给s.t连一条边,对答案的贡献是k/a. 如果a>b,分两种情况.如果k

【HDOJ】4729 An Easy Problem for Elfness

其实是求树上的路径间的数据第K大的题目.果断主席树 + LCA.初始流量是这条路径上的最小值.若a<=b,显然直接为s->t建立pipe可以使流量最优:否则,对[0, 10**4]二分得到boundry,使得boundry * n_edge - sum_edge <= k/b, 或者建立s->t,然后不断extend s->t. 1 /* 4729 */ 2 #include <iostream> 3 #include <sstream> 4 #inc

[HDU4729]An Easy Problem for Elfness

[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\)路径上的权值最小

HDU 2601 An easy problem(暴力枚举/质因子分解)

An easy problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 7963    Accepted Submission(s): 1920 Problem Description When Teddy was a child , he was always thinking about some simple math p

hdu 2055 An easy problem (java)

问题: 开始尝试用字符做数组元素,但是并没有用.在判断语句时把a z排出了. An easy problem Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 16516    Accepted Submission(s): 11096 Problem Description we define f(A) = 1, f(a) = -1,

主席树 hdu 4348

题意:有一个由n个数组成的序列,有4中操作: 1.C l r d [l,r]这段区间都加上d 2.Q l r 询问[l,r]这段区间的和 3.H l r t 询问之前t时间[l,r]的区间和 4.B t 回到t时间,且下一秒的时间从t开始 按时间建立主席树,主席树上的每一棵线段树维护[1,n]这段序列的信息,这里成段更新的时候要注意,以往写线段树的时候,都是把lazy标记向下传,但是写主席树的时候每一次下传,那么新的节点数就会非常多,会爆内存,所以我们不把lazy操作下传,只是在询问的时候,最后

数据结构(主席树):HDU 5654 xiaoxin and his watermelon candy

Problem Description During his six grade summer vacation, xiaoxin got lots of watermelon candies from his leader when he did his internship at Tencent. Each watermelon candy has it's sweetness which denoted by an integer number. xiaoxin is very smart

HDU 5475 An easy problem(线段树)

题目链接: 戳我 题目大意: 一个计算器只有两种运算,初始化 X = 1 第一种操作: X 乘以 一个数,获得新的 X 第二种操作: 当前的 X 除以 一个数 输出  X % M 其中 1 y 表示第一种操作,即 X  = X * y 2 n 表示 X 除以 前面的 第 n 个操作的那个 y,保证 第 n 个表示的是 1,即数据合法 注意:X 在进行操作的时候不要除模, 而是输出的时候除模,即要保证 X 进行操作的时候除模是和不除模情况下是相等的. 比如: 3 10 1 5 1 3 2 1,如果

2015上海网络赛 HDU 5475 An easy problem 线段树

题意就不说了 思路:线段树,维护区间乘积.2操作就将要除的点更新为1. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<set> 9 #include<stri