hdu 4729 An Easy Problem for Elfness,函数式线段树
来源:互联网 发布:西门子840d攻丝编程 编辑:程序博客网 时间:2024/06/05 10:09
hdu 4729 An Easy Problem for Elfness,函数式线段树
13年成都网赛的题。
主要是问一个树上的某两个点间的路径,你可以对某些边增加一些流量,最多这个路径上能流过多少流量。
题目意思比较复杂(废话多),最大流量可以分成这几种情况:
1、增加一条边,剩下的费用用来增加这条边的流量,加上本来两点间的流量。
2、所有的费用用来建新边,加上本来的流量。
3、在本来的边上增加流量,求最大能通过流量。
最近怎么老根各种树过不去。
函数式线段树能够处理某些树上路径问题。
简单来说就是这样,以边权为下标建线段树。
想象每个点都有一个[1..cmax]的线段树,而且,每个点的树是从父节点的树插入一个之间的边的流量的点得到。
这样呢,我们可以用u、v、lca[u,v]的线段树来表示u到v路径的线段树。
u、v路径的线段树就是t[u]+t[v]-2*t[lca]。
现在问题就是找到最大的c,使得费用足够使得小于c的边都变成c。
线段树是个好东西,O(logn)可以搞定。
需要记录两个值,总权值v,总边数cnt。
如果(总共能添加的边流量val>=左区间的上界m*总边数cnt-总权值v),那就向右边递归,否则向左边。
具体看代码吧:
13年成都网赛的题。
主要是问一个树上的某两个点间的路径,你可以对某些边增加一些流量,最多这个路径上能流过多少流量。
题目意思比较复杂(废话多),最大流量可以分成这几种情况:
1、增加一条边,剩下的费用用来增加这条边的流量,加上本来两点间的流量。
2、所有的费用用来建新边,加上本来的流量。
3、在本来的边上增加流量,求最大能通过流量。
最近怎么老根各种树过不去。
函数式线段树能够处理某些树上路径问题。
简单来说就是这样,以边权为下标建线段树。
想象每个点都有一个[1..cmax]的线段树,而且,每个点的树是从父节点的树插入一个之间的边的流量的点得到。
这样呢,我们可以用u、v、lca[u,v]的线段树来表示u到v路径的线段树。
u、v路径的线段树就是t[u]+t[v]-2*t[lca]。
现在问题就是找到最大的c,使得费用足够使得小于c的边都变成c。
线段树是个好东西,O(logn)可以搞定。
需要记录两个值,总权值v,总边数cnt。
如果(总共能添加的边流量val>=左区间的上界m*总边数cnt-总权值v),那就向右边递归,否则向左边。
具体看代码吧:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;#define NN 100010struct que{ int s,t,k,a,b,lca; void init(int y,int u,int i,int o,int p){ s=y;t=u;k=i;a=o;b=p; }}q[NN];vector<pair<int,int> > fi[NN];void addedge(int fr,int to,int val){ fi[fr].push_back(make_pair(to,val));}int root[NN],tott;struct segtree{ int ls,rs,l,r,v,cnt; void init(int val=0){ls=rs=l=r=0;v=val;cnt=0;}}t[NN*20];void init_segtree(){ tott=0; t[0].init();}int build(int l,int r){ int p=++tott; t[p].l=l;t[p].r=r;t[p].v=t[p].cnt=0; if (l==r){ t[p].ls=t[p].rs=0;return p; } int m=(l+r)>>1; t[p].ls=build(l,m); t[p].rs=build(m+1,r); return p;}int insert(int pos,int num,int pas){ int p=++tott; t[p]=t[pas]; t[p].v+=pos; t[p].cnt+=num; if (t[p].l==t[p].r) return p; int m=(t[p].l+t[p].r)>>1; if (pos<=m) t[p].ls=insert(pos,num,t[p].ls); else t[p].rs=insert(pos,num,t[p].rs); return p;}int query1(int s,int to,int lca,int tc=0,int tv=0){ return t[s].r*(tc+t[s].cnt+t[to].cnt-t[lca].cnt-t[lca].cnt)-(tv+t[s].v+t[to].v-t[lca].v-t[lca].v);}int queryc(int s,int to,int lca){ return t[s].cnt+t[to].cnt-t[lca].cnt-t[lca].cnt;}int queryv(int s,int to,int lca){ return t[s].v+t[to].v-t[lca].v-t[lca].v;}int query(int s,int to,int lca,int val,int tc,int tv){ if (t[s].l==t[s].r){ if (query1(s,to,lca,tc,tv)<=val) return t[s].l; else return t[s].l-1; } int tmp,m=t[s].l+t[s].r>>1; if ((tmp=query1(t[s].ls,t[to].ls,t[lca].ls,tc,tv))<=val){ return query(t[s].rs,t[to].rs,t[lca].rs,val,tc+queryc(t[s].ls,t[to].ls,t[lca].ls),tv+queryv(t[s].ls,t[to].ls,t[lca].ls)); } else { return query(t[s].ls,t[to].ls,t[lca].ls,val,tc,tv); }}void dfs(int u,int fa,int val){ int i,v,sz; if (u!=1){ root[u]=insert(val,1,root[fa]); } sz=fi[u].size(); for(i=0;i<sz;++i){ v=fi[u][i].first; if (v!=fa){ dfs(v,u,fi[u][i].second); } }}vector<pair<int,int> > vec[NN];int set[NN],vis[NN];int dep[NN];int findset(int x){return x==set[x]?x:set[x]=findset(set[x]);}void init_lca(int n){ for(int i=1;i<=n;++i){vec[i].clear();set[i]=i;vis[i]=0;}}void tarjan(int u,int fa,int de){ int i; dep[u]=de; int v,sz=fi[u].size(); for(i=0;i<sz;++i){ v=fi[u][i].first; if (v!=fa){ tarjan(v,u,de+1); set[v]=u; } } vis[u]=1; sz=vec[u].size(); for(i=0;i<sz;++i){ v=vec[u][i].first; if (vis[v]) q[vec[u][i].second].lca=findset(v); }}int main(){ //freopen("4729in.txt","r",stdin); int tcas,cas,n,m,cmax,a,b,c,s,t,k; int i,val,tp,tmp,ans,lca; scanf("%d",&tcas); for(cas=1;cas<=tcas;++cas){ scanf("%d%d",&n,&m); for(i=1;i<=n;++i) fi[i].clear(); cmax=0; for(i=1;i<n;++i){ scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); addedge(b,a,c); if (c>cmax) cmax=c; } init_lca(n); for(i=1;i<=m;++i){ scanf("%d%d%d%d%d",&s,&t,&k,&a,&b); q[i].init(s,t,k,a,b); vec[s].push_back(make_pair(t,i)); vec[t].push_back(make_pair(s,i)); } tarjan(1,-1,0); init_segtree(); root[1]=build(1,cmax); dfs(1,-1,0); printf("Case #%d:\n",cas); for(i=1;i<=m;++i){ a=q[i].a;b=q[i].b;k=q[i].k;s=q[i].s;t=q[i].t;lca=q[i].lca; tmp=query(root[s],root[t],root[lca],0,0,0); if (k>=a) ans=max(k/a+tmp,(k-a)/b+1+tmp); else ans=0; val=k/b; tp=dep[s]+dep[t]-dep[lca]*2; tmp=query1(root[s],root[t],root[lca]); if (tmp<=val){ ans=max(ans,cmax+(val-tmp)/tp); } else { ans=max(query(root[s],root[t],root[lca],val,0,0),ans); } printf("%d\n",ans); } } return 0;}
0 0
- hdu 4729 An Easy Problem for Elfness,函数式线段树
- 【HDU】4729 An Easy Problem for Elfness 可持久化线段树——主席树
- 【树链剖分】 HDU 4729 An Easy Problem for Elfness 二分
- HDU 4729 An Easy Problem for Elfness(树链剖分 + 二分)
- 【主席树】 HDOJ 4729 An Easy Problem for Elfness
- An Easy Problem for Elfness
- HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)
- HDU 4729 An Easy Problem for Elfness(树上主席树+LCA+二分)
- hdu 4729 An Easy Problem for Elfness (树链剖分-入边-二分-查区间最值)
- hdu 5475 An easy problem(线段树)
- hdu 5475 An easy problem 线段树
- hdu 5475 An easy problem (线段树)
- HDU-5475-An easy problem【线段树】
- hdu-5475-An easy problem-线段树求乘积
- HDU 5475:An easy problem 这题也能用线段树做???
- hdu 5475 An easy problem(线段树)
- hdu 5475 An easy problem(线段树单点更新)
- [HDU 5475] An easy problem (线段树)
- C#中图片与BASE64码互相转换
- 非递归实现快速排序算法
- C语言中的printf与scanf函数
- 自开发SQL语句分析工具--Z_SQL_EXPLAIN
- mysql 总结(以后继续补充)
- hdu 4729 An Easy Problem for Elfness,函数式线段树
- 深入理解cookie与session
- 成都天钻调查公司
- 自开发显示表索引程序
- Java学习之Servlet-doGet()与doPost()
- 自开发对比报表的工具程序
- 数据库连接池
- Setup Factory 脚本编辑方法
- 设计模式笔记-桥模式