思路:這個樹鏈剖分其實還是比較明顯的。將邊按權值排序後插入線段樹,然後用線段樹查詢區間中比某個數小的數和,以及這樣的數的個數。當a<=b時,就全部建新的管子。
對於a>b的情況比較 建一條由s->t的管子後將這根管子容量擴到最大能得到的容量 與 將所有預算都用來擴大管子容量不建新管子得到的最大容量 做比較 ,選最大的。
擴容量能得到的最大權值可以同過二分列舉答案,用樹鏈剖分判斷。
#include#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#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;
inthead[maxn],vi[maxn],dep[maxn],w[maxn],top[maxn],son[maxn],sz[maxn],fa[maxn],e,id;
intval[maxn];
intnum[maxn],cnt;
struct
point
}lis[maxn];
struct
edgeedge[maxn*3
];struct
tree
}tree[maxn*3
];void
init()
void add(int u,int v,int
val)
void buildtree(int l,int r,int
po)void update(int i,int c,int
po) tree[po].p[++tree[po].c]=c;
tree[po].q[tree[po].c]=tree[po].q[tree[po].c-1]+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)
int mid=tree[po].mid();
if(r<=mid)
return
getmin(l,r,lson(po));
else
if(l>=mid+1
)
return
getmin(l,r,rson(po));
else
}ll getans(
int l,int r,ll val,int
po)
if(pos>1
)
return0;
}int mid=tree[po].mid();
if(r<=mid)
return
getans(l,r,val,lson(po));
else
if(l>=mid+1
)
return
getans(l,r,val,rson(po));
else
}void dfs(int u,int
val)
}void build(int u,int
ti)}
ll need(ll val,
int u,int
v) ans+=getans(w[f1],w[u],val,1
); 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,1
);
//coutreturn
ans;
}void calc(int u,int
v,ll k,ll a,ll b)
ans=min(ans,(ll)getmin(w[f1],w[u],1
)); 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],1
)); ll capacity=0
;
if(kif(a<=b)
if(k>=a)
capacity=(k-a)/b+1+ans;
ll l,r,mid,temp;
l=0,r=k/b+ans+1
;
while(l+1
if(r>=1
)
if(need(r,x,y)*b<=k&&r>l)
l=r;
printf(
"%i64d\n
",max(capacity,l));
return;}
intmain()
dfs(
1,1200000000
); memset(vi,
0,sizeof
(vi));
build(
1,1);
sort(lis+1,lis+id+1
); buildtree(
1,n,1
);
for(i=1;i<=n;i++)
printf(
"case #%d:\n
",++case);
for(i=1;i<=m;i++)
}return0;
}
hdu 4729 樹鏈剖分 二分
此題一看就知道是樹鏈剖分,模板題!可憐我模板少抄個字母,在這兩百多行的 裡找bug找了三個多小時啊!解題思路 對於要求的x,y點,先可以求得不加任何操作的最大流量p,c1為建造乙個路的話費,c2為增加乙個容量的花費,如果c1 c2,那麼結果就為p k c1。否則,如果先建一條路,那麼最大的流量是m ...
樹鏈剖分 樹鏈剖分講解
好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...
HDU3966 樹鏈剖分
題目 aragorn s story 題意 給一棵樹,並給定各個點權的值,然後有3種操作 i c1 c2 k 把c1與c2的路徑上的所有點權值加上k d c1 c2 k 把c1與c2的路徑上的所有點權值減去k q c 查詢節點編號為c的權值 分析 典型的樹鏈剖分題目,先進行剖分,然後用線段樹去維護即...