zoukankan      html  css  js  c++  java
  • 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

    解题思路:

    相当于动态统计一棵树的带权重心。

    怎么搞呢?

    序列上会不会。

    不就是二分吗,这东西会形成一个单峰函数。

    证明我不会不过可以拿这个代码看一下。

    #include<cstdio>
    #include<algorithm>
    typedef long long lnt;
    const int N=10;
    int a[]={0,101,2131,321,432,213,3124,5342,2323,5432,2323,
                 122,2511,321,432,2513,3132,5342,2323,5432,2323,
               102,211,321,432,2133,3124,5342,2323,5432,2323,
               12,2131,321,43124,52323,5432,2323,
               102,231,21,43413224,5342,323,5432,3,
               153,2131,213213,3124,5342,2323,543323,
               102,21,321,43242,233,5432,2323,
               502,2131,321,4,5342,2323,5432,2323
               102,2131,321,53,2323,5432,2323,
               12302,2131,3212,432,122342,2323,5432,2323,
               103212,2131,321,432,21324,5312,28323,5432,23
               1102,2131,321,432,213,3124,5342,2323,5432,3,
               1023,2131,321,432,213,31124,5342,2323,543223,
               103212,2131,321,432,213,3124,5342,2323,5432,3,
               102,2131,321,432,5213,3124,5342,2323,5432,2323,
               102,2131,321,432,213,3124,5342,2323,5432,2323,};
    lnt fan(int pos)
    {
        lnt ans=0;
        for(int i=1;i<=N;i++)
        {
            ans+=1ll*std::abs(pos-i)*a[i];
        }
        return ans;
    }
    int main()
    {
        for(int i=1;i<=N;i++)
            printf("%I64d ",fan(i));
        return 0;
    }
    View Code

    所以就是单峰了。

    所以说就可以在树上做同样的试探动作。

    如果一个点的答案更优秀那么答案就在其子树中。

    可以知道一个点答案就是向父亲走时加入容斥。

    那个公式我就不推了QAQ。

    维护三个答案,子到父代价,子树代价,子树全职和。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 typedef long long lnt;
      5 const int N=100010;
      6 struct pnt{
      7     int fa;
      8     int hd;
      9     int hf;
     10     int dp;
     11     int wgt;
     12     int ind;
     13     lnt dis;
     14     lnt sum;
     15     lnt diss;
     16     lnt disf;
     17     bool vis;
     18 }p[N];
     19 struct ent{
     20     int twd;
     21     int lst;
     22     lnt vls;
     23 }e[N<<2];
     24 int rt;
     25 int n,m;
     26 int cnt;
     27 int dfn;
     28 int root;
     29 int size;
     30 int maxsize;
     31 int lg[N<<2];
     32 int eula[N<<2][21];
     33 void ade(int f,int t,lnt v)
     34 {
     35     cnt++;
     36     e[cnt].twd=t;
     37     e[cnt].vls=v;
     38     e[cnt].lst=p[f].hd;
     39     p[f].hd=cnt;
     40     return ;
     41 }
     42 void adf(int f,int t,int lin)
     43 {
     44     cnt++;
     45     e[cnt].twd=t;
     46     e[cnt].vls=lin;
     47     e[cnt].lst=p[f].hf;
     48     p[f].hf=cnt;
     49     return ;
     50 }
     51 void E_dfs(int x,int f)
     52 {
     53     eula[++dfn][0]=x;
     54     p[x].ind=dfn;
     55     p[x].dp=p[f].dp+1;
     56     for(int i=p[x].hd;i;i=e[i].lst)
     57     {
     58         int to=e[i].twd;
     59         if(to==f)
     60             continue;
     61         p[to].dis=p[x].dis+e[i].vls;
     62         E_dfs(to,x);
     63         eula[++dfn][0]=x;
     64     }
     65     return ;
     66 }
     67 int Emin(int x,int y)
     68 {
     69     return p[x].dp<p[y].dp?x:y;
     70 }
     71 int Lca(int x,int y)
     72 {
     73     x=p[x].ind;
     74     y=p[y].ind;
     75     if(x>y)
     76         std::swap(x,y);
     77     int l=lg[y-x+1];
     78     return Emin(eula[x][l],eula[y-(1<<l)+1][l]);
     79 }
     80 lnt Dis(int x,int y)
     81 {
     82     int z=Lca(x,y);
     83     return p[x].dis+p[y].dis-2*p[z].dis;
     84 }
     85 void grc_dfs(int x,int f)
     86 {
     87     p[x].wgt=1;
     88     int maxs=-1;
     89     for(int i=p[x].hd;i;i=e[i].lst)
     90     {
     91         int to=e[i].twd;
     92         if(to==f||p[to].vis)
     93             continue;
     94         grc_dfs(to,x);
     95         p[x].wgt+=p[to].wgt;
     96         if(p[to].wgt>maxs)
     97             maxs=p[to].wgt;
     98     }
     99     maxs=std::max(maxs,size-p[x].wgt);
    100     if(maxs<maxsize)
    101     {
    102         maxsize=maxs;
    103         root=x;
    104     }
    105     return ;
    106 }
    107 void bin_dfs(int x,int f)
    108 {
    109     p[x].fa=f;
    110     p[x].vis=true;
    111     int tmp=size;
    112     for(int i=p[x].hd;i;i=e[i].lst)
    113     {
    114         int to=e[i].twd;
    115         if(p[to].vis)
    116             continue;
    117         root=0;
    118         if(p[x].wgt<p[to].wgt)
    119             size=tmp-p[x].wgt;
    120         else
    121             size=p[to].wgt;
    122         maxsize=0x3f3f3f3f;
    123         grc_dfs(to,to);
    124         adf(x,root,to);
    125         bin_dfs(root,x);
    126     }
    127     return ;
    128 }
    129 void update(int x,lnt y)
    130 {
    131     p[x].sum+=y;
    132     for(int i=x;p[i].fa;i=p[i].fa)
    133     {
    134         p[p[i].fa].sum+=y;
    135         lnt tmp=Dis(x,p[i].fa)*y;
    136         p[i].disf+=tmp;
    137         p[p[i].fa].diss+=tmp;
    138     }
    139     return ;
    140 }
    141 lnt assess(int x)
    142 {
    143     lnt ans=p[x].diss;
    144     for(int i=x;p[i].fa;i=p[i].fa)
    145     {
    146         lnt tmp=Dis(x,p[i].fa);
    147         ans+=tmp*(p[p[i].fa].sum-p[i].sum);
    148         ans+=p[p[i].fa].diss-p[i].disf;
    149     }
    150     return ans;
    151 }
    152 lnt Query(void)
    153 {
    154     bool has=true;
    155     lnt ans=assess(rt);
    156     int lastpos=rt;
    157     while(has)
    158     {
    159         has=false;
    160         for(int i=p[lastpos].hf;i;i=e[i].lst)
    161         {
    162             int to=e[i].twd;
    163             lnt tmp=assess(e[i].vls);
    164             if(tmp<ans)
    165             {
    166                 has=true;
    167                 ans=assess(to);
    168                 lastpos=to;
    169                 break;
    170             }
    171         }
    172     }
    173     return ans;
    174 }
    175 int main()
    176 {
    177     scanf("%d%d",&n,&m);
    178     for(int i=1;i<n;i++)
    179     {
    180         int a,b;
    181         lnt c;
    182         scanf("%d%d%lld",&a,&b,&c);
    183         ade(a,b,c);
    184         ade(b,a,c);
    185     }
    186     E_dfs(1,1);
    187     for(int i=2;i<=dfn;i++)
    188         lg[i]=lg[i>>1]+1;
    189     for(int i=1;i<=20;i++)
    190         for(int j=1;j+(1<<i)-1<=dfn;j++)
    191             eula[j][i]=Emin(eula[j][i-1],eula[j+(1<<(i-1))][i-1]);
    192     root=0;
    193     size=n;
    194     maxsize=0x3f3f3f3f;
    195     grc_dfs(1,1);
    196     rt=root;
    197     bin_dfs(root,0);
    198     while(m--)
    199     {
    200         int x,y;
    201         scanf("%d%d",&x,&y);
    202         update(x,y);
    203         printf("%lld
    ",Query());
    204     }
    205     return 0;
    206 }
  • 相关阅读:
    SQL进阶系列之2自连接
    SQL进阶系列之0窗口函数
    SQL进阶系列之1CASE表达式
    Python for Email
    数据分析的统计基础5
    利用Python openpyxl操作Excel
    SQL基础篇(MICK)
    数据分析的统计基础4
    数据分析的统计基础3
    数据分析的统计基础2
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10160367.html
Copyright © 2011-2022 走看看