zoukankan      html  css  js  c++  java
  • BZOJ3924 ZJOI2015 幻想乡战略游戏 【动态点分治】

    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


    点分树,每次沿着点分树上的父亲关系进行跳,因为可以发现在一条链上带权重心一定是单调的,又因为只会跳跃log次,所以可以保证时间效率

    #include<bits/stdc++.h>
    using namespace std;
    #define N 200010
    #define LL long long
    int read(){
        int ans=0,w=1;char c=getchar();
        while(!isdigit(c)&&c!='-')c=getchar();
        if(c=='-')c=getchar(),w=-1;
        while(isdigit(c))ans=ans*10+c-'0',c=getchar();
        return ans*w;
    }
    struct Edge{int v,next,cost;}E[N<<1];
    int head[N],tot=0;
    void add(int u,int v,int cost){
        E[++tot]=(Edge){v,head[u],cost};
        head[u]=tot; 
    }
    int n,m;
    int dep[N],d[N],st[N<<1][22],sta[N<<1];
    int id[N],ind=0,ip[N];
    void dfs(int u,int fa){
        sta[++ind]=u;ip[u]=ind;
        if(!id[u])id[u]=ind;
        dep[ind]=dep[ip[fa]]+1;
        for(int i=head[u];i;i=E[i].next){
            int v=E[i].v;
            if(v==fa)continue;
            d[v]=d[u]+E[i].cost;
            dfs(v,u);
            sta[++ind]=u;
            dep[ind]=dep[ip[fa]+1];
        }
    }
    void ST(){
        for(int i=1;i<=ind;i++)st[i][0]=i;
        for(int k=1;k<=18;k++)
            for(int i=1;i+(1<<k)-1<=ind;i++){
                int x=st[i][k-1],y=st[i+(1<<(k-1))][k-1];
                if(dep[x]<dep[y])st[i][k]=x;
                else st[i][k]=y;
            }
    } 
    int lca(int u,int v){
        if(id[u]>id[v])swap(u,v);
        int k=log2(id[v]-id[u]+1);
        int x=st[id[u]][k],y=st[id[v]-(1<<k)+1][k];
        if(dep[x]<dep[y])return sta[x];
        else return sta[y];
    }
    int dis(int x,int y){return d[x]+d[y]-2*d[lca(x,y)];}
    int rt,tree_siz,f[N],siz[N],fa[N];
    LL ans[N],ans1[N],sum[N];
    bool vis[N];
    void getroot(int u,int fa){
        siz[u]=1;
        f[u]=0;
        for(int i=head[u];i;i=E[i].next){
            int v=E[i].v;
            if(v==fa||vis[v])continue;
            getroot(v,u);
            siz[u]+=siz[v];
            f[u]=max(f[u],siz[v]);
        }
        f[u]=max(f[u],tree_siz-siz[u]);
        if(f[u]<f[rt])rt=u;
    }
    void solve(int u,int father){
        vis[u]=1;
        fa[u]=father;
        for(int i=head[u];i;i=E[i].next){
            int v=E[i].v;
            if(vis[v])continue;
            tree_siz=siz[v];
            getroot(v,rt=0); 
            solve(rt,u);
        }
    }
    LL calc(LL u){
        LL res=ans[u];
        for(int i=u;fa[i];i=fa[i]){
            LL dt=dis(fa[i],u);
            res+=(ans[fa[i]]-ans1[i]);
            res+=dt*(sum[fa[i]]-sum[i]);
        }
        return res;
    }
    void modify(int u,int val){
        sum[u]+=val;
        for(int i=u;fa[i];i=fa[i]){
            LL len=dis(fa[i],u);
            sum[fa[i]]+=val;
            ans1[i]+=val*len;
            ans[fa[i]]+=val*len;
        }
    }
    int lastans=1;
    LL query(int u){
        LL res=calc(u);
        for(int i=head[u];i;i=E[i].next)
            if(calc(E[i].v)<res)
                return query(E[i].v);
        lastans=u;
        return res;
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<n;i++){
            int u=read(),v=read(),cost=read();
            add(u,v,cost);
            add(v,u,cost);
        }
        dfs(1,0);
        ST();
        tree_siz=f[0]=n;
        getroot(1,0);
        solve(rt,0);
        for(int i=1;i<=m;i++){
            int a=read(),b=read();
            modify(a,b);
            printf("%lld
    ",query(lastans));
        }
        return 0;
    }
  • 相关阅读:
    (转)HapMap简介
    FASTQ 数据质量统计工具
    CentOS7利用systemctl添加自定义系统服务【转】
    python的pymysql使用方法【转】
    Python使用MySQL数据库【转】
    MySQL全备+binlog恢复方法之伪装master【原创】
    利用binlogserver恢复单表实验【转】
    shell文本左右对齐排版【转】
    关于GTID模式下备份时 --set-gtid-purged=OFF 参数的实验【转】
    mysqlbinlog恢复数据注意事项【转】
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676369.html
Copyright © 2011-2022 走看看