• Bzoj3924 [Zjoi2015]幻想乡战略游戏


    Time Limit: 100 Sec  Memory Limit: 256 MB
    Submit: 817  Solved: 376

    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)。数据保证任何时刻每个点上的军队数量都是非负的。 

    Output

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

    Sample Input

    10 5
    1 2 1
    2 3 1
    2 4 1
    1 5 1
    2 61
    2 7 1
    5 8 1
    7 91
    1 10 1
    3 1
    2 1
    8 1
    3 1
    4 1

    Sample Output

    0
    1
    4
    5
    6

    HINT

     

    对于所有数据,1<=c<=1000, 0<=|e|<=1000, n<=105, Q<=105

     

     

    Source

    树 动态树分治

    询问树的加权重心

    可以发现这么一个性质:随便选一个点,如果加权重心不在当前点,那么从当前点往加权重心走,花费肯定单调减小。

    从上次的答案开始走,用动态点分治维护和查询将当前点作为补给站的花费,然后暴力枚举走向哪个方向

    qsum里i少减了一个1,调了俩小时

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 #define LL long long
      9 using namespace std;
     10 const int INF=0x3f3f3f3f;
     11 const int mxn=120010;
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 //inline int max(int a,int b){return a>b?a:b;}
     19 //inline LL max(LL a,LL b){return a>b?a:b;}
     20 //inline int min(int a,int b){return a<b?a:b;}
     21 //inline LL min(LL a,LL b){return a<b?a:b;}
     22 struct edge{
     23     int v,nxt,w;
     24 }e[mxn<<1];
     25 int hd[mxn],mct=0;
     26 void add_edge(int u,int v,int w){
     27     e[++mct].v=v;e[mct].nxt=hd[u];e[mct].w=w;hd[u]=mct;return;
     28 }
     29 int sz[mxn],mc[mxn],rt=0,smm;
     30 //int f[mxn][20];
     31 bool vis[mxn];
     32 void DFS_sz(int u,int fa){
     33     sz[u]=1;mc[u]=0;
     34     for(int i=hd[u],v;i;i=e[i].nxt){
     35         v=e[i].v;
     36         if(v==fa || vis[v])continue;
     37         DFS_sz(v,u);
     38         sz[u]+=sz[v];
     39         mc[u]=max(mc[u],sz[v]);
     40     }
     41     mc[u]=max(mc[u],smm-sz[u]);
     42     if(mc[u]<=mc[rt])rt=u;
     43     return;
     44 }
     45 int dis[mxn][20],act[mxn];
     46 int g[mxn][20];//ansi
     47 LL cost1[mxn],cost2[mxn];
     48 int num1[mxn],num2[mxn];
     49 //
     50 void getship(int x,int fa,int an,int dist){
     51 //        printf("x:%d  fa:%d an:%d dist:%d
    ",x,fa,an,dist);
     52     for(int i=hd[x];i;i=e[i].nxt){
     53         int v=e[i].v;
     54         if(v==fa || vis[v])continue;
     55         g[v][++act[v]]=an;//新一级祖先 
     56         dis[v][act[v]]=dist+e[i].w;//距离 
     57         getship(v,x,an,dist+e[i].w);
     58     }
     59     return;
     60 }
     61 //
     62 LL nowans=0;int nowpos=0;
     63 int a[mxn];//军队人数 
     64 //
     65 void solve(int x){
     66 //    printf("solve:%d
    ",x);
     67     vis[x]=1;
     68     getship(x,0,x,0);
     69     g[x][++act[x]]=x;
     70     for(int i=hd[x];i;i=e[i].nxt){
     71         int v=e[i].v;
     72         if(vis[v])continue;
     73         smm=sz[v];
     74         rt=0;
     75         DFS_sz(v,x);
     76         solve(rt);
     77     }
     78     return;
     79 }
     80 void update(int u,int E){
     81     num1[u]+=E;
     82     for(int i=act[u];i>1;i--){
     83 //        int dist=dis[g[u][i]][act[g[u][i]]-1];
     84         int dist=dis[u][i-1];
     85         cost2[g[u][i]]+=(LL)dist*E;
     86         cost1[g[u][i-1]]+=(LL)dist*E;
     87         num2[g[u][i]]+=E;
     88         num1[g[u][i-1]]+=E;
     89     }
     90     return;
     91 }
     92 LL qsum(int x){
     93 //    printf("Qsum:%d   
    ",x);
     94     LL res=cost1[x];
     95     for(int i=act[x];i>1;i--){
     96         LL dist=dis[x][i-1];
     97         res+=cost1[g[x][i-1]]-cost2[g[x][i]];
     98         res+=(LL)dist*(num1[g[x][i-1]]-num2[g[x][i]]);
     99     }
    100     return res;
    101 }
    102 void Move(int x,int from){
    103 //    printf("move:%d
    ",x);
    104     for(int i=hd[x];i;i=e[i].nxt){
    105         int v=e[i].v;
    106         if(v==from)continue;
    107         LL co=qsum(v);
    108         if(co<nowans){
    109             nowans=co;
    110             nowpos=v;
    111             Move(v,x);
    112             break;
    113         }
    114     }
    115     return;
    116 }
    117 int n,Q;
    118 int main(){
    119 //    freopen("in.txt","r",stdin);
    120 //    freopen("zjoi15_tree1.in","r",stdin);
    121 //    freopen("zjoi15_tree1.out","w",stdout);
    122     int i,j;
    123     n=read();Q=read();
    124     int a,b,c,u,e;
    125     for(i=1;i<n;i++){
    126         a=read();b=read();c=read();
    127         add_edge(a,b,c);
    128         add_edge(b,a,c);
    129     }
    130     mc[rt=0]=INF;
    131     smm=n;
    132     DFS_sz(1,0);
    133     int rot=rt;
    134     solve(rt);
    135     nowpos=rot;
    136     while(Q--){
    137         u=read();e=read();
    138         update(u,e);
    139         nowans=qsum(nowpos);
    140         Move(nowpos,0);
    141         printf("%lld
    ",nowans);
    142     }
    143     return 0;
    144 }
    Time Limit: 100 Sec  Memory Limit: 256 MB
    Submit: 817  Solved: 376
    [Submit][Status][Discuss]

    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)。数据保证任何时刻每个点上的军队数量都是非负的。 

    Output

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

    Sample Input

    10 5
    1 2 1
    2 3 1
    2 4 1
    1 5 1
    2 61
    2 7 1
    5 8 1
    7 91
    1 10 1
    3 1
    2 1
    8 1
    3 1
    4 1

    Sample Output

    0
    1
    4
    5
    6

    HINT

     

    对于所有数据,1<=c<=1000, 0<=|e|<=1000, n<=105, Q<=105

     

     

    Source

  • 相关阅读:
    Mac 配置 php-fpm 时出现'/private/etc/php-fpm.conf': No such file or directory (2)
    Lua数学库
    Nginx在Windows上启动、停止的命令
    Javascript虚拟机
    Tiled Forward Shading Links
    Xcode同一个Workspace中两个工程依赖于Undefined Symbol Error
    Clang: Undefined symbols, but it is there using nm.
    MVC+Ext.net零基础学习记录(二)
    MVC+Ext.net零基础学习记录(一)
    根据某个字符串查找整个数据库
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6723342.html
Copyright © 2020-2023  润新知