hdu 4729 樹鏈剖分

2022-05-22 06:24:11 字數 3282 閱讀 7321

思路:這個樹鏈剖分其實還是比較明顯的。將邊按權值排序後插入線段樹,然後用線段樹查詢區間中比某個數小的數和,以及這樣的數的個數。當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的權值 分析 典型的樹鏈剖分題目,先進行剖分,然後用線段樹去維護即...