P4069 [SDOI2016] 游戏
P4069 [SDOI2016] 游戏
题目描述
Alice 和 Bob 在玩一个游戏。
游戏在一棵有
有时,Alice 会选择一条从
有时,Bob 会选择一条从
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。
数据范围
对于所有数据,
Solution:
这下不得不在机房打 game 了
看到树上路径问题我们不难想到树链剖分.
看到贡献
我们以
由于
然后我们仔细的思考一下贡献:
对于上行链:
对于下行链:
然后要注意一下的是,由于这题我们需要区间查询,所以我们在 query 时需要注意查询的边界问题,详见代码。
然后这题就换乐的做完了。
Code:
#include<bits/stdc++.h> #define ll long long #define int long long const ll inf=123456789123456789; const int N=1e5+5; using namespace std; int n,m,tot; ll dis[N],dep[N],dfn[N],fa[N],top[N],son[N],siz[N],rid[N]; struct line{ ll k,b; }q[N*20]; inline ll hight(ll x,int id) { return q[id].k*(dis[rid[x]])+q[id].b; } inline ll Min(ll x,ll y){return x<y ? x : y;} struct Segment_Tree{ struct Tree{ int id; ll ans; }t[N<<2]; #define ls x<<1 #define rs x<<1|1 void build(int x,int l,int r) { t[x].ans=inf; if(l==r)return ; int mid=l+r>>1; build(ls,l,mid);build(rs,mid+1,r); } void pushup(int x){t[x].ans=Min(t[x].ans,Min(t[ls].ans,t[rs].ans));} void upd(int x,int l,int r,int L,int R,int k) { int mid=l+r>>1; if(L<=l&&r<=R) { ll h0=hight(l,t[x].id),h1=hight(mid,t[x].id),h2=hight(r,t[x].id); ll H0=hight(l,k),H1=hight(mid,k),H2=hight(r,k); t[x].ans=Min(t[x].ans,Min(H0,H2)); if(H0<h0&&H2<h2){t[x].id=k;return ;} if(H0>=h0&&H2>=h2){return ;} if(q[k].k<q[t[x].id].k) { if(H1<h1){upd(ls,l,mid,L,R,t[x].id);t[x].id=k;} else upd(rs,mid+1,r,L,R,k); } else { if(H1<h1){upd(rs,mid+1,r,L,R,t[x].id);t[x].id=k;} else upd(ls,l,mid,L,R,k); } } if(L<=mid)upd(ls,l,mid,L,R,k); if(mid<R) upd(rs,mid+1,r,L,R,k); pushup(x); return ; } void query(int x,int l,int r,int L,int R,ll &res) { if(L<=l&&r<=R){res=Min(res,t[x].ans);return ;} ll tmp=Min(hight(max(l,L),t[x].id),hight(min(r,R),t[x].id)); if(t[x].id)res=Min(res,tmp); int mid=l+r>>1; if(L<=mid)query(ls,l,mid,L,R,res); if(mid<R) query(rs,mid+1,r,L,R,res); } #undef ls #undef rs }T; struct Node{ int y; ll w; }; vector<Node> E[N]; void dfs1(int x,int ff) { dep[x]=dep[ff]+1;fa[x]=ff;siz[x]=1; for(Node u : E[x]) { if(u.y==fa[x])continue; dis[u.y]=dis[x]+u.w; dfs1(u.y,x); siz[x]+=siz[u.y]; son[x] = siz[son[x]] > siz[u.y] ? son[x] : u.y; } } void dfs2(int x,int tp) { dfn[x]=++dfn[0];top[x]=tp;rid[dfn[0]]=x; if(!son[x])return ; dfs2(son[x],tp); for(Node u : E[x]) { if(u.y==fa[x]||u.y==son[x])continue; dfs2(u.y,u.y); } } int LCA(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y] ? x : y; } void chain_upd(int x,int y) { while(top[x]!=top[y]) { T.upd(1,1,n,dfn[top[x]],dfn[x],tot); x=fa[top[x]]; } T.upd(1,1,n,dfn[y],dfn[x],tot); } ll chain_query(int s,int t) { int lca=LCA(s,t),x=s,y=t; ll res=inf; while(top[x]!=top[lca]) { T.query(1,1,n,dfn[top[x]],dfn[x],res); x=fa[top[x]]; } while(top[y]!=top[lca]) { T.query(1,1,n,dfn[top[y]],dfn[y],res); y=fa[top[y]]; } if(dfn[x]<dfn[y]) { T.query(1,1,n,dfn[x],dfn[y],res); } else { T.query(1,1,n,dfn[y],dfn[x],res); } return res; } void work() { cin>>n>>m; for(int i=1,x,y;i<n;i++) { ll w; cin>>x>>y>>w; E[x].push_back({y,w}); E[y].push_back({x,w}); } dfs1(1,0);dfs2(1,1); T.build(1,1,n); q[tot]={0,inf}; for(int i=1,opt,s,t;i<=m;i++) { ll k,b; cin>>opt>>s>>t; int lca=LCA(s,t); if(opt&1) { cin>>k>>b; q[++tot]={-k,k*dis[s]+b};chain_upd(s,lca); q[++tot]={k,k*(dis[s]-dis[lca]*2)+b};chain_upd(t,lca); } else { ll ans=chain_query(s,t); printf("%lld\n",ans); } } } #undef ll #undef int int main() { //freopen("P4069.in","r",stdin); //freopen("P4069.out","w",stdout); work(); return 0; }