bzoj 4515 [Sdoi2016]游戏 线段树维护凸包
来源:互联网 发布:怎么恢复数据 编辑:程序博客网 时间:2024/05/16 13:05
先树链剖分转成区间问题。
S到T的路径可以拆成S-lca和lca-T。
设d[r]表示根到r的距离。
对于S-lca中的点r,加的值为:
对于lca-T中的点r,加的值为:
这样就可以转成将一个区间的每个点r的值与一次函数在d[r]处的值取min。
在线段树上维护这个东西。
线段树上每个点维护一条跨过当前点的线段。
修改一段区间时对于线段树上受影响的点,如果在当前区间,增加的线段与当前线段没有交点那么将当前线段修改为在上面的那条。
否则求交点,然后往下递归传一条线段。
注意由于区间查询所以需要pushdown
区间查询时每到一个区间用当前区间的直线更新答案,然后正常往下查询。
#include <bits/stdc++.h>using namespace std;#define N 110000#define ll long long#define ls l,mid,now<<1#define rs mid+1,r,now<<1|1#define inf 123456789123456789llint n,m,tot,cnt;int head[N],nex[N<<1],to[N<<1],val[N<<1];int deep[N],fa[N],son[N],top[N],pos[N],bel[N],size[N];ll d[N],v[N<<3];struct node{ ll a,b; node(){} node(ll a,ll b):a(a),b(b){} ll cal(ll x){return a*x+b;}}tr[N<<3],v1;double ins(node r1,node r2){return (double)(r2.b-r1.b)/(r1.a-r2.a);}void add(int x,int y,int z){ tot++; nex[tot]=head[x];head[x]=tot; to[tot]=y;val[tot]=z;}void dfs1(int x,int y){ size[x]=1;fa[x]=y; deep[x]=deep[y]+1; for(int i=head[x];i;i=nex[i]) if(to[i]!=y) { d[to[i]]=d[x]+val[i]; dfs1(to[i],x); size[x]+=size[to[i]]; son[x]=size[to[i]]>size[son[x]] ? to[i]:son[x]; } }void dfs2(int x,int y,int tp){ top[x]=tp; pos[x]=++cnt;bel[cnt]=x; if(son[x])dfs2(son[x],x,tp); for(int i=head[x];i;i=nex[i]) if(to[i]!=y&&to[i]!=son[x]) dfs2(to[i],x,to[i]);}void build(int l,int r,int now){ tr[now]=node(0,inf); v[now]=inf; if(l==r)return; int mid=(l+r)>>1; build(ls);build(rs);}int lca(int x,int y){ while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])swap(x,y); x=fa[top[x]]; } return deep[x]<deep[y] ? x:y;}void pushup(int x){ v[x]=min(v[x],v[x<<1]); v[x]=min(v[x],v[x<<1|1]);}void insert(int l,int r,int now,node v1){ ll lv=v1.cal(d[bel[l]]),rv=v1.cal(d[bel[r]]); ll lp=tr[now].cal(d[bel[l]]),rp=tr[now].cal(d[bel[r]]); if(lv>=lp&&rv>=rp)return; if(lv<=lp&&rv<=rp)tr[now]=v1; else { int mid=(l+r)>>1; double x=ins(v1,tr[now]),t=(double)(d[bel[mid]]+d[bel[mid+1]])/2.0; if(lv>lp) { if(x>=t)insert(rs,v1); else insert(ls,tr[now]),tr[now]=v1; } else { if(x<=t)insert(ls,v1); else insert(rs,tr[now]),tr[now]=v1; } } v[now]=min(v[now],tr[now].cal(d[bel[l]])); v[now]=min(v[now],tr[now].cal(d[bel[r]])); pushup(now);}void update(int l,int r,int now,int lq,int rq){ if(lq<=l&&r<=rq) {insert(l,r,now,v1);return;} int mid=(l+r)>>1; if(mid>=lq)update(ls,lq,rq); if(mid<rq) update(rs,lq,rq); pushup(now);}void update(int x,int y){ while(top[x]!=top[y]) { update(1,n,1,pos[top[x]],pos[x]); x=fa[top[x]]; } update(1,n,1,pos[y],pos[x]);}ll get(int l,int r,int now,int lq,int rq){ l=max(l,lq);r=min(r,rq); return min(tr[now].cal(d[bel[l]]),tr[now].cal(d[bel[r]]));}ll query(int l,int r,int now,int lq,int rq){ if(lq<=l&&r<=rq)return v[now]; int mid=(l+r)>>1; ll ret=get(l,r,now,lq,rq); if(mid>=lq)ret=min(ret,query(ls,lq,rq)); if(mid<rq) ret=min(ret,query(rs,lq,rq)); return ret;}ll query(int x,int y){ ll ret=inf; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])swap(x,y); ret=min(ret,query(1,n,1,pos[top[x]],pos[x])); x=fa[top[x]]; } if(deep[x]<deep[y])swap(x,y); ret=min(ret,query(1,n,1,pos[y],pos[x])); return ret;}int main(){ memset(v,127,sizeof(v)); scanf("%d%d",&n,&m); for(int i=1,x,y,v;i<n;i++) { scanf("%d%d%d",&x,&y,&v); add(x,y,v);add(y,x,v); } dfs1(1,0); dfs2(1,0,1); build(1,n,1); for(int tp,s,t,a,b;m--;) { scanf("%d",&tp); if(tp==1) { scanf("%d%d%d%d",&s,&t,&a,&b); int lc=lca(s,t); v1=node(-a,a*d[s]+b);update(s,lc); v1=node(a,a*d[s]+b-2*a*d[lc]);update(t,lc); } else { scanf("%d%d",&s,&t); printf("%lld\n",query(s,t)); } } return 0;}
0 0
- bzoj 4515 [Sdoi2016]游戏 线段树维护凸包
- Bzoj 4515 线段树 SDOI2016 游戏 Game
- bzoj 4515: [Sdoi2016]游戏 树链剖分+线段树
- [树链剖分 线段树 标记永久化] BZOJ 4515 [Sdoi2016]游戏
- bzoj 4515: [Sdoi2016]游戏(树链剖分+线段树)
- BZOJ 4515 SDOI2016 游戏
- BZOJ 4515: [Sdoi2016]游戏
- BZOJ 4515 [Sdoi2016]游戏
- BZOJ 4515 [Sdoi2016]游戏
- bzoj 4515: [Sdoi2016]游戏
- bzoj 4515: [Sdoi2016]游戏 树链剖分
- 【BZOJ4519】【Sdoi2016】游戏 线段树
- 【bzoj4515】【SDOI2016】【游戏】【线段树+树链剖分】
- BZOJ 2402 陶陶的难题II 二分答案+斜率优化+树链剖分+线段树维护凸包
- bzoj 2402 陶陶的难题II 01分数规划 树链剖分 线段树维护凸包
- [树链剖分+李超线段树] BZOJ4515: [Sdoi2016]游戏
- [树链剖分 李超线段树] BZOJ4515 [Sdoi2016] 游戏
- 【树链剖分+李超线段树】BZOJ4515(Sdoi2016)[游戏]题解
- android软件开发之webView.addJavascriptInterface循环渐进【二】
- Android---ThinkPad开启虚拟化增强(VT)
- poj3421(多重集排列,唯一分解定理)
- 坚持#第78天~不赖床不赖床,手机闹铃远离床!
- 序列化的一些小事情
- bzoj 4515 [Sdoi2016]游戏 线段树维护凸包
- hdu1054 Strategic Game(最小顶点覆盖)
- bzoj usaco 1233 神题。。
- HDU4801【DFS】
- 欢迎使用CSDN-markdown编辑器
- 数据库学习笔记(二)
- 安卓 字符串明明一样 为什么equals不一样?
- EL表达式和JSTL标签
- Intersection