[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;
}
posted @ 2019-10-23 16:54  lsoi_ljk123  阅读(132)  评论(0编辑  收藏  举报