BZOJ3924 [Zjoi2015]幻想乡战略游戏

Description

 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了。 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决。 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来。在游戏中,幽香可能在空地上增加或者减少一些军队。同时,幽香可以在一个空地上放置一个补给站。 如果补给站在点u上,并且空地v上有dv个单位的军队,那么幽香每天就要花费dv×dist(u,v)的金钱来补给这些军队。由于幽香需要补给所有的军队,因此幽香总共就要花费为Sigma(Dv*dist(u,v),其中1<=V<=N)的代价。其中dist(u,v)表示u个v在树上的距离(唯一路径的权和)。 因为游戏的规定,幽香只能选择一个空地作为补给站。在游戏的过程中,幽香可能会在某些空地上制造一些军队,也可能会减少某些空地上的军队,进行了这样的操作以后,出于经济上的考虑,幽香往往可以移动他的补给站从而省一些钱。但是由于这个游戏的地图是在太大了,幽香无法轻易的进行最优的安排,你能帮帮她吗? 你可以假定一开始所有空地上都没有军队。

Input

第一行两个数n和Q分别表示树的点数和幽香操作的个数,其中点从1到n标号。 

接下来n-1行,每行三个正整数a,b,c,表示a和b之间有一条边权为c的边。 

接下来Q行,每行两个数u,e,表示幽香在点u上放了e单位个军队

(如果e<0,就相当于是幽香在u上减少了|e|单位个军队,说白了就是du←du+e)。

数据保证任何时刻每个点上的军队数量都是非负的。 

1<=c<=1000, 0<=|e|<=1000, n<=10^5, Q<=10^5

对于所有数据,这个树上所有点的度数都不超过20

N,Q>=1

Output

 对于幽香的每个操作,输出操作完成以后,每天的最小花费,也即如果幽香选择最优的补给点进行补给时的花费。 

Sample Input

10 5
1 2 1
2 3 1
2 4 1
1 5 1
2 6 1
2 7 1
5 8 1
7 9 1
1 10 1
3 1
2 1
8 1
3 1
4 1

Sample Output

0
1
4
5
6

/**************************************************************

    Problem: 3924

    User: ictsing

    Language: C++

    Result: Accepted

    Time:10024 ms

    Memory:12936 kb

****************************************************************/

 

//BZOJ3924 [Zjoi2015]幻想乡战略游戏

#include <iostream>

#include <cstdio>

using namespace std;

int ecnt=0;

const int mt = 100000+5;

int to[mt<<1],nxt[mt<<1],adj[mt],w[mt<<1];

int sum[mt<<2];

int sz[mt],dep[mt],fa[mt];

int pos[mt],top[mt],opt[mt],dis[mt];

typedef long long ll;

int tot=0;

int rt=1;

int _clock=0;

int n,m;

ll ans=0;

inline int read()

{

    int num=0,flag=1;

    char ch;

    do{

      ch=getchar();

      if(ch=='-') flag=-1;

    }while(ch<'0'||ch>'9');

    do{

      num=num*10+ch-'0';

      ch=getchar();

    }while(ch>='0'&&ch<='9');

    return num*flag;

}

void adde(int u,int v,int ww)

{

    ecnt++,to[ecnt]=v,nxt[ecnt]=adj[u],w[ecnt]=ww,adj[u]=ecnt;

}

void pushup(int rt)

{

    sum[rt]=sum[rt<<1]+sum[rt<<1|1];

}

void update(int rt,int l,int r,int pos,int val)

{

    if(l==r)

    {

        sum[rt]+=val;

        return ;

    }

    int mid=(l+r)>>1;

    if(pos<=mid) update(rt<<1,l,mid,pos,val);

    else update(rt<<1|1,mid+1,r,pos,val);

    pushup(rt);

}

int query(int rt,int l,int r,int lft,int rgt)

{

    if(lft<=l&&r<=rgt)

        return sum[rt];

    int mid=(l+r)>>1;

    int res=0;

    if(lft<=mid) res+=query(rt<<1,l,mid,lft,rgt);

    if(rgt>mid) res+=query(rt<<1|1,mid+1,r,lft,rgt);

    return res;

}

void dfs1(int u)

{

    sz[u]=1;dep[u]=dep[fa[u]]+1;

    for(int i=adj[u];i;i=nxt[i])

    {

        int v=to[i];

        if(fa[u]==v) continue;

        fa[v]=u;

        dis[v]=dis[u]+w[i];

        dfs1(v);

        sz[u]+=sz[v];

        if(sz[v]>sz[opt[u]])

            opt[u]=v;

    }

}

void dfs2(int u,int chain)

{

    pos[u]=++_clock;

    top[u]=chain;

    if(opt[u]) dfs2(opt[u],chain);

    else return ;

    for(int i=adj[u];i;i=nxt[i])

    {

        int v=to[i];

        if(v^fa[u]&&v^opt[u])

        dfs2(v,v);

    }

}

int lca(int u,int v)

{

    while(top[u]^top[v])

        if(dep[top[u]]>dep[top[v]]) u=fa[top[u]];

        else v=fa[top[v]];

    return dep[u]<dep[v]?u:v;

}

int diss(int u,int v)

{

    return dis[u]+dis[v]-2*dis[lca(u,v)];

}

ll cal(int x,int qwq)

{

    if(x==fa[rt])

    {

        int t1=query(1,1,n,pos[rt],pos[rt]+sz[rt]-1);

        int t2=tot-t1;

        return ans+1ll*(t1-t2)*qwq;

    }

    else

    {

        int t2=query(1,1,n,pos[x],pos[x]+sz[x]-1);

        int t1=tot-t2;

        return ans+1ll*(t1-t2)*qwq;

    }

}

void move(int u)

{

    ll mn=1ll*1e60,tmp;

    int id=0;

    for(int i=adj[u];i;i=nxt[i])

    {

        int v=to[i];

        tmp=1ll*cal(v,w[i]);

        if(tmp<mn) mn=tmp,id=v;

    }

    if(mn<ans) rt=id,ans=mn,move(rt);

}

int main()

{

    n=read(),m=read();

    for(int i=1;i<=n-1;i++)

    {

        int u=read(),v=read(),ww=read();

        adde(u,v,ww),adde(v,u,ww);

    }

    dfs1(1);

    dfs2(1,1);

    while(m--)

    {

        int u=read(),qwq=read();

        ans+=1ll*qwq*diss(u,rt);

        tot+=qwq;

        update(1,1,n,pos[u],qwq);

        move(rt);

        printf("%lld\n",ans);

    }

    return 0;

}

 

评论

热度(5)