hdu 4729 树链剖分
思路:这个树链剖分其实还是比较明显的。将边按权值排序后插入线段树,然后用线段树查找区间中比某个数小的数和,以及这样的数的个数。当A<=B时,就全部建新的管子。
对于A>B的情况比较 建一条由S->T的管子后将这根管子容量扩到最大能得到的容量 与 将所有预算都用来扩大管子容量不建新管子得到的最大容量 做比较 ,选最大的。
扩容量能得到的最大权值可以同过二分枚举答案,用树链剖分判断。
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pb push_back
#define mp make_pair
#define Maxn 200010
#define Maxm 400010
#define LL __int64
#define Abs(x) ((x)>0?(x):(-x))
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
#define inf 100000
#define lowbit(x) (x&(-x))
#define clr(x,y) memset(x,y,sizeof(x))
#define Mod 1000000007
using namespace std;
int head[Maxn],vi[Maxn],dep[Maxn],w[Maxn],top[Maxn],son[Maxn],sz[Maxn],fa[Maxn],e,id;
int val[Maxn];
int num[Maxn],cnt;
struct Point{
int val,i;
int operator <(const Point &temp) const{
return val<temp.val;
}
}lis[Maxn];
struct Edge{
int u,v,next;
int val;
}edge[Maxn*];
struct Tree{
int l,r,c;
int *p;
int *q;
int mid(){
return (l+r)>>;
}
}tree[Maxn*];
void init()
{
clr(head,-);clr(vi,);
e=;id=;
}
void add(int u,int v,int val)
{
edge[e].u=u,edge[e].v=v,edge[e].val=val,edge[e].next=head[u],head[u]=e++;
}
void BuildTree(int l,int r,int po)
{
tree[po].l=l,tree[po].r=r,tree[po].c=;
tree[po].p=new int[r-l+];
tree[po].q=new int[r-l+];
tree[po].q[]=;
if(l==r)
return ;
int mid=tree[po].mid();
BuildTree(l,mid,lson(po));
BuildTree(mid+,r,rson(po));
}
void update(int i,int c,int po)
{
if(tree[po].l==tree[po].r){
tree[po].p[++tree[po].c]=c;
tree[po].q[tree[po].c]=tree[po].q[tree[po].c-]+c;
return ;
}
tree[po].p[++tree[po].c]=c;
tree[po].q[tree[po].c]=tree[po].q[tree[po].c-]+c;
int mid=tree[po].mid();
if(i<=mid)
update(i,c,lson(po));
else
update(i,c,rson(po));
}
int getmin(int l,int r,int po)
{
if(l<=tree[po].l&&tree[po].r<=r){
return tree[po].p[];
}
int mid=tree[po].mid();
if(r<=mid)
return getmin(l,r,lson(po));
else if(l>=mid+)
return getmin(l,r,rson(po));
else{
return min(getmin(l,mid,lson(po)),getmin(mid+,r,rson(po)));
}
}
LL getans(int l,int r,LL val,int po)
{
if(l<=tree[po].l&&tree[po].r<=r){
int pos=lower_bound(tree[po].p+,tree[po].p+tree[po].c+,val)-tree[po].p;
if(pos>tree[po].c){
cnt+=tree[po].c;
return tree[po].q[tree[po].c];
}
if(pos>){
cnt+=pos-;
return tree[po].q[pos-];
}
return ;
}
int mid=tree[po].mid();
if(r<=mid)
return getans(l,r,val,lson(po));
else if(l>=mid+)
return getans(l,r,val,rson(po));
else{
return getans(l,mid,val,lson(po))+getans(mid+,r,val,rson(po));
}
}
void dfs(int u,int val)
{
vi[u]=;
int i,v;
son[u]=,sz[u]=;
num[u]=val;
for(i=head[u];i!=-;i=edge[i].next){
v=edge[i].v;
if(vi[v]) continue;
dep[v]=dep[u]+;
fa[v]=u;
dfs(v,edge[i].val);
if(sz[v]>sz[son[u]])son[u]=v;
sz[u]+=sz[v];
}
}
void build(int u,int ti)
{
int i,v;
w[u]=++id;top[u]=ti;vi[u]=;
lis[id].i=id,lis[id].val=num[u];
if(son[u]) build(son[u],ti);
for(i=head[u];i!=-;i=edge[i].next){
v=edge[i].v;
if(vi[v]||v==son[u]) continue;
build(v,v);
}
}
LL need(LL val,int u,int v)
{
int f1=top[u],f2=top[v];
cnt=;
LL ans=;
// cout<<u<<" "<<f1<<" "<<v<<" "<<f2<<" "<<w[f1]<<" "<<w[u]<<endl;
while(f1!=f2){
if(dep[f1]<dep[f2]){
swap(f1,f2),swap(u,v);
}
ans+=getans(w[f1],w[u],val,);
u=fa[f1];f1=top[u];
}
if(dep[u]>dep[v])
swap(u,v);
if(u!=v)
ans+=getans(w[son[u]],w[v],val,);
//cout<<u<<" "<<v<<" "<<val<<" "<<cnt<<" "<<ans<<" "<<val*cnt-ans<<endl;
ans=val*(LL)cnt-ans;
return ans;
}
void calc(int u,int v,LL k,LL a,LL b)
{
int x=u,y=v;
int f1=top[u],f2=top[v];
LL ans=;
while(f1!=f2){
if(dep[f1]<dep[f2]){
swap(f1,f2),swap(u,v);
}
ans=min(ans,(LL)getmin(w[f1],w[u],));
u=fa[f1];f1=top[u];
}
if(dep[u]>dep[v])
swap(u,v);
if(u!=v)
ans=min(ans,(LL)getmin(w[son[u]],w[v],));
LL capacity=;
if(k<min(a,b)){
printf("%I64d\n",ans);
return ;
}
if(a<=b){
printf("%I64d\n",k/a+ans);
return ;
}
if(k>=a)
capacity=(k-a)/b++ans;
LL l,r,mid,temp;
l=,r=k/b+ans+;
while(l+<r){
mid=(l+r)>>;
temp=need(mid,x,y);
temp*=b;
if(temp<=k)
l=mid;
else
r=mid-;
}
if(r>=)
if(need(r,x,y)*b<=k&&r>l)
l=r;
printf("%I64d\n",max(capacity,l));
return ;
}
int main()
{
int t,n,m,i,j,u,v,val,q,a,b,k,Case=;
scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
for(i=;i<n;i++){
scanf("%d%d%d",&u,&v,&val);
add(u,v,val);
add(v,u,val);
}
dfs(,);
memset(vi,,sizeof(vi));
build(,);
sort(lis+,lis+id+);
BuildTree(,n,);
for(i=;i<=n;i++){
update(lis[i].i,lis[i].val,);
}
printf("Case #%d:\n",++Case);
for(i=;i<=m;i++){
scanf("%d%d%d%d%d",&u,&v,&k,&a,&b);
calc(u,v,k,a,b);
}
}
return ;
}
hdu 4729 树链剖分的更多相关文章
- hdu 5893 (树链剖分+合并)
List wants to travel Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ...
- hdu 5052 树链剖分
Yaoge’s maximum profit Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/ ...
- hdu 4897 树链剖分(重轻链)
Little Devil I Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- hdu 5274 树链剖分
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HDU 3966 (树链剖分+线段树)
Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- HDU 3966 /// 树链剖分+树状数组
题意: http://acm.hdu.edu.cn/showproblem.php?pid=3966 给一棵树,并给定各个点权的值,然后有3种操作: I x y z : 把x到y的路径上的所有点权值加 ...
- hdu 3966 树链剖分
思路:树链剖分入门题,我这门入得好苦啊,程序很快写出来了,可是在LCA过程中把update函数里的左右边界位置写反了,一直RE到死. #pragma comment(linker, "/ST ...
- HDU 5274(树链剖分)
树链剖分第一题QAQ,纪念下 #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream ...
随机推荐
- Unity3d:播放物理目录下的MP3文件
u3d里,是支持播放MP3文件的,但要放到资源里,不支持播放物理目录下的MP3文件.由于界面上无需显示,只是当作背景音乐来播放,所以想到调用c#的组件来解决此问题.主要代码都在附件中,根据需要加到自己 ...
- C# 特性详解(上)
特性(attribute)是被指定给某一声明的一则附加的声明性信息. 元数据,就是C#中封装的一些类,无法修改.类成员的特性被称为元数据中的注释. 1.什么是特性 1)属性与特性的区别 属性 ...
- ActiveMQ集成到Spring
[http://wentao365.iteye.com/blog/1560934] spring配置文件applicationContext.xml <?xml version="1. ...
- INNO&&DELPHI
好久不弄delphi了,再次见到inno,居然不知所措~ 让人亲切的 var,又见到了.而如今,到处可见. 整目录复制 Flags: igNoreversion recursesubdirs crea ...
- 8.实现(Realization)
实现关系是用来描述接口和实现接口的类或者构建结构之间的关系,接口是操作的集合,而这些操作就用于规定类或者构建结构的一种服务. 在接口和类之间的实现关系中,类实现了接口,类中的操作实现了接口中所声明的操 ...
- 学习JQuery中文文档之map()函数和get()函数
今天学到一个新的函数map(). map(callback) 官方概述: 将一组元素转换成其他数组(不论是否是元素数组) 你可以用这个函数来建立一个列表,不论是值.属性还是CSS样式,或者其他特别形式 ...
- 不用FTP使用SecureCRT上传下载文件,并解决rz、sz command not found异常
使用SSH终端操作Linux/UNIX时,很多时候需要传一些文件到服务器上,或说从服务器上下载一些文件,这类文件传输动作一般使用FTP即可,但是需要架设FTP Server,每次传输不太方便,还要另外 ...
- IE调试方法(一)<转>
前面两篇关于IE11开发人员工具的文章,我们分别介绍了两个新的功能:UI响应工具和内存分析工具,今天为大家介绍一个老功能:网络工具,虽然是在IE9开始已经加入了这个工具,但是在IE11中还有有很多改进 ...
- 无法将类型为 excel.applicationclass 的 com 强制转换为接口类型 的解决方法。
今天碰到客户的电脑在导出EXCEL的时候提示,无法将类型为 excel.applicationclass 的 com 强制转换为接口类型 excel._application 的问题 最后用下面的方法 ...
- C++ Primer 学习笔记_46_STL实践与分析(20)--容器特有的算法
STL实践与分析 --容器特有的算法 与其它顺序容器所支持的操作相比,标准库为list容器定义了更精细的操作集合,使它不必仅仅依赖于泛型操作.当中非常大的一个原因就是list容器不是依照内存中的顺序进 ...