AC日记——[ZJOI2015]幻想乡战略游戏 洛谷 P3345

[ZJOI2015]幻想乡战略游戏

 

思路:

  树剖暴力转移;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 100005
#define ll long long
struct TreeNodeType {
    ll l,r,sum,mid;
};
struct TreeNodeType tree[maxn<<2];
ll n,m,head[maxn],E[maxn<<1],V[maxn<<1],W[maxn<<1],cnt;
ll id[maxn],sum[maxn],f[maxn],top[maxn],deep[maxn],size[maxn];
ll lar[maxn],dis[maxn],End[maxn],live,P=1,Sum;
inline void in(ll &now)
{
    ll if_z=1;now=0;
    char Cget=getchar();
    while(Cget>'9'||Cget<'0')
    {
        if(Cget=='-') if_z=-1;
        Cget=getchar();
    }
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
    now*=if_z;
}
inline void edge_add(ll u,ll v,ll w)
{
    E[++cnt]=head[u],V[cnt]=v,W[cnt]=w,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,W[cnt]=w,head[v]=cnt;
}
void dfs1(ll now,ll fa)
{
    f[now]=fa,deep[now]=deep[fa]+1,size[now]=1;
    for(ll i=head[now];i;i=E[i])
    {
        if(V[i]==f[now]) continue;
        dis[V[i]]=dis[now]+W[i],dfs1(V[i],now),size[now]+=size[V[i]];
        if(size[lar[now]]<size[V[i]]) lar[now]=V[i];
    }
}
void dfs2(ll now,ll chain)
{
    top[now]=chain,id[now]=++cnt;
    if(lar[now]) dfs2(lar[now],chain);
    for(ll i=head[now];i;i=E[i])
    {
        if(V[i]==lar[now]||V[i]==f[now]) continue;
        dfs2(V[i],V[i]);
    }
    End[now]=cnt;
}
ll find(ll x,ll y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) y=f[top[y]];
        else x=f[top[x]];
    }
    return deep[x]<deep[y]?x:y;
}
void build(ll now,ll l,ll r)
{
    tree[now].l=l,tree[now].r=r;
    if(l==r) return;tree[now].mid=l+r>>1;
    build(now<<1,l,tree[now].mid);
    build(now<<1|1,tree[now].mid+1,r);
}
void add(ll now,ll to,ll x)
{
    if(tree[now].l==tree[now].r)
    {
        tree[now].sum+=x;
        return;
    }
    if(to<=tree[now].mid) add(now<<1,to,x);
    else add(now<<1|1,to,x);
    tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
}
ll query(ll now,ll to)
{
    if(tree[now].l>=id[to]&&tree[now].r<=End[to]) return tree[now].sum;
    ll res=0;if(id[to]<=tree[now].mid) res+=query(now<<1,to);
    if(End[to]>tree[now].mid) res+=query(now<<1|1,to);return res;
}
ll Try(ll to)
{
    ll pos=query(1,to),res=live;
    res-=pos*(dis[to]-dis[P]);
    res+=(Sum-pos)*(dis[to]-dis[P]);
    return res;
}
ll TryF()
{
    ll pos=query(1,P),res=live;
    res-=(Sum-pos)*(dis[P]-dis[f[P]]);
    res+=pos*(dis[P]-dis[f[P]]);
    return res;
}
ll Search()
{
    ll res=0,res_=live,pos;
    for(ll i=head[P];i;i=E[i])
    {
        if(V[i]==f[P])
        {
            pos=TryF();
            if(pos<res_) res=V[i],res_=pos;
        }
        else
        {
            pos=Try(V[i]);
            if(pos<res_) res=V[i],res_=pos;
        }
    }
    if(res) P=res,live=res_;
    return res;
}
int main()
{
    //freopen("data.txt","r",stdin);
    freopen("zjoi15_tree.in","r",stdin);
    freopen("zjoi15_tree.out","w",stdout);
    in(n),in(m);ll u,v,w,lca,tmp;
    for(ll i=1;i<n;i++) in(u),in(v),in(w),edge_add(u,v,w);
    cnt=0,dfs1(1,0),dfs2(1,1),build(1,1,n);
    while(m--)
    {
        in(u),in(w),add(1,id[u],w),lca=find(P,u),Sum+=w;
        live+=w*(dis[u]+dis[P]-dis[lca]*2);
        while(Search());printf("%lld\n",live);
    }
    return 0;
}

 

posted @ 2017-06-18 21:36  IIIIIIIIIU  阅读(262)  评论(0编辑  收藏  举报