[SDOI2016]游戏题解
[SDOI2016]游戏题解
这道题太恶心了,调了我整整一晚上,
结果发现是一个bi——错误,多多捂脸
这道题比之前的题多了一个初始化和区间查询的操作,
主要是区间查询恶心
因为要区间查询,所以必须维护区间最低点,
修改和查询操作被改得面目全非。
我们要维护的话,必须从现值,子值,新值,具体的不好多说:
看代码吧:
#include<bits/stdc++.h>
#define ll long long
#define lc x<<1
#define rc x<<1|1
using namespace std;
const int N=1e5+6;
const ll inf=123456789123456789ll;
int n,m,cnt=0,d[N],ff[N],siz[N],top[N],son[N],num[N],head[N];
int t1,t2,opt,s,tt,LCA,dfn=0;
ll kk,bb,t3,dis[N],w[N];
struct tree{ll k,b,minx;}t[N<<2];
struct edge{int nxt,to; ll w;}e[N<<1];
inline void add(int u,int v,ll w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,head[u]=cnt;}
inline ll read(){
ll T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
void dfs(int x,int fa){
d[x]=d[fa]+1,ff[x]=fa,siz[x]=1; int maxt=0;
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa){
dis[e[i].to]=dis[x]+e[i].w,dfs(e[i].to,x),siz[x]+=siz[e[i].to];
if(siz[maxt]<siz[e[i].to]) maxt=e[i].to;
}
son[x]=maxt;
}
void dfs2(int x,int topx){
num[x]=++dfn,top[x]=topx,w[dfn]=dis[x];
//cout<<x<<" "<<num[x]<<" "<<top[x]<<" "<<son[x]<<" "<<dis[x]<<endl;
if(son[x]) dfs2(son[x],topx);
for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=ff[x]&&e[i].to!=son[x]) dfs2(e[i].to,e[i].to);
}
void build(int l,int r,int x){
t[x].k=0,t[x].b=inf,t[x].minx=inf;
if(l==r) return;
int mid=l+r>>1;
build(l,mid,lc),build(mid+1,r,rc);
}
inline ll f(tree u,ll v){return u.k*v+u.b;}
void update(int l,int r,int p,int q,ll k,ll b,int x){
int mid=l+r>>1;
if(p<=l&&r<=q){
if(l==r){if(k*w[l]+b<f(t[x],w[l])) t[x].k=k,t[x].b=b,t[x].minx=f(t[x],w[l]); return;}
if(k>t[x].k){
if(k*w[mid]+b<f(t[x],w[mid])) update(mid+1,r,p,q,t[x].k,t[x].b,rc),t[x].k=k,t[x].b=b;
else update(l,mid,p,q,k,b,lc);
}
else{
if(k*w[mid]+b<f(t[x],w[mid])) update(l,mid,p,q,t[x].k,t[x].b,lc),t[x].k=k,t[x].b=b;
else update(mid+1,r,p,q,k,b,rc);
}
t[x].minx=min(t[x].minx,min(f(t[x],w[l]),f(t[x],w[r]))),t[x].minx=min(t[x].minx,min(t[lc].minx,t[rc].minx));
return;
}
if(p<=mid) update(l,mid,p,q,k,b,lc);
if(q>mid) update(mid+1,r,p,q,k,b,rc);
t[x].minx=min(t[x].minx,min(t[lc].minx,t[rc].minx));
}
ll query(int l,int r,int p,int q,int x){
if(p<=l&&r<=q) return t[x].minx;
int mid=l+r>>1; ll ans=inf;
if(t[x].b!=inf){
int u=max(l,p),v=min(r,q);
ans=min(f(t[x],w[u]),f(t[x],w[v]));
}
if(p<=mid) ans=min(ans,query(l,mid,p,q,lc));
if(q>mid) ans=min(ans,query(mid+1,r,p,q,rc));
return ans;
}
void lj_update(int x,int y,ll k,ll b){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
update(1,n,num[top[x]],num[x],k,b,1);
x=ff[top[x]];
}
if(d[x]>d[y]) swap(x,y);
update(1,n,num[x],num[y],k,b,1);
}
ll lj_query(int x,int y){
ll ans=inf;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
ans=min(ans,query(1,n,num[top[x]],num[x],1));
x=ff[top[x]];
}
if(d[x]>d[y]) swap(x,y);
ans=min(ans,query(1,n,num[x],num[y],1));
return ans;
}
int lca(int x,int y){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
x=ff[top[x]];
}
if(d[x]>d[y]) swap(x,y);
return x;
}
int main(){
n=read(),m=read();
for(int i=1;i<n;++i) t1=read(),t2=read(),t3=read(),add(t1,t2,t3),add(t2,t1,t3);
dfs(1,0),dfs2(1,1),build(1,n,1);
for(int i=1;i<=m;++i){
opt=read(),s=read(),tt=read();
if(opt==2) printf("%lld\n",lj_query(s,tt));
else kk=read(),bb=read(),LCA=lca(s,tt),lj_update(s,LCA,-kk,kk*dis[s]+bb),lj_update(LCA,tt,kk,kk*(dis[s]-2ll*dis[LCA])+bb);
}
return 0;
}