zoukankan      html  css  js  c++  java
  • [loj2135]幻想乡战略游戏

    以1为根建树,令$D_{i}$为$i$子树内所有节点$d_{i}$之和

    令$ans_{i}$为节点$i$的答案,令$fa$为$i$的父亲,则$ans_{i}=ans_{fa}+dis(i,fa)(D_{1}-2D_{i})$

    节点$i e 1$是最大值的必要条件是其$2D_{i}>D_{1}$,否则一定有$ans_{i}ge ans_{fa}$

    换言之,我们只需要考虑$i=1$或$2D_{i}>D_{1}$的节点,根据$d_{i}$非负的性质,不难证明这是一条以1为端点的链

    对于这条链上的节点$i e 1$,必然有$ans_{i}<ans_{fa}$,因此最终即求这条链最底部的节点

    对其求dfs序,这个最底部的节点也是dfs序最大的节点,线段树维护$D_{i}$最大值二分即可

    由于修改是链修改,需要使用树链剖分,复杂度为$o(nlog^{2}n)$,可以通过

    另外还需要查询$x$答案,即$ans_{1}+sum_{i为x祖先或i=x,i e 1}dis(i,fa)(D_{1}-2D_{i})$,同样用树链剖分维护即可

    (关于其点分的做法复杂度并不正确,因为还需要枚举每一个点的度数来找到移动的节点)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define ll long long
      5 #define L (k<<1)
      6 #define R (L+1)
      7 #define mid (l+r>>1)
      8 struct Edge{
      9     int nex,to,len;
     10 }edge[N<<1];
     11 int E,n,m,x,y,z,D,head[N],fa[N],sz[N],dep[N],mx[N],dfn[N],idfn[N],top[N],tag[N<<2],f[N<<2];
     12 ll ans,val[N<<2],sum[N<<2];
     13 void add(int x,int y,int z){
     14     edge[E].nex=head[x];
     15     edge[E].to=y;
     16     edge[E].len=z;
     17     head[x]=E++;
     18 }
     19 void dfs1(int k,int f,int sh){
     20     fa[k]=f;
     21     sz[k]=1;
     22     dep[k]=sh;
     23     for(int i=head[k];i!=-1;i=edge[i].nex)
     24         if (edge[i].to!=f){
     25             dfs1(edge[i].to,k,sh+edge[i].len);
     26             sz[k]+=sz[edge[i].to];
     27             if (sz[mx[k]]<sz[edge[i].to])mx[k]=edge[i].to;
     28         }
     29 }
     30 void dfs2(int k,int fa,int t){
     31     dfn[k]=++dfn[0];
     32     idfn[dfn[0]]=k;
     33     top[k]=t;
     34     if (mx[k])dfs2(mx[k],k,t);
     35     for(int i=head[k];i!=-1;i=edge[i].nex)
     36         if ((edge[i].to!=fa)&&(edge[i].to!=mx[k]))dfs2(edge[i].to,k,edge[i].to);
     37 }
     38 void up(int k){
     39     f[k]=max(f[L],f[R]);
     40     sum[k]=sum[L]+sum[R];
     41 }
     42 void upd(int k,int x){
     43     tag[k]+=x;
     44     f[k]+=x;
     45     sum[k]+=x*val[k]; 
     46 }
     47 void down(int k){
     48     upd(L,tag[k]);
     49     upd(R,tag[k]);
     50     tag[k]=0;
     51 }
     52 void build(int k,int l,int r){
     53     if (l==r){
     54         val[k]=dep[idfn[l]]-dep[fa[idfn[l]]];
     55         return;
     56     }
     57     build(L,l,mid);
     58     build(R,mid+1,r);
     59     val[k]=val[L]+val[R];
     60 }
     61 void update(int k,int l,int r,int x,int y,int z){
     62     if ((l>y)||(x>r))return;
     63     if ((x<=l)&&(r<=y)){
     64         upd(k,z);
     65         return;
     66     }
     67     down(k);
     68     update(L,l,mid,x,y,z);
     69     update(R,mid+1,r,x,y,z);
     70     up(k);
     71 }
     72 void update(int k,int x){
     73     while (k){
     74         update(1,1,n,dfn[top[k]],dfn[k],x);
     75         k=fa[top[k]];
     76     }
     77 }
     78 int find(int k,int l,int r){
     79     if (l==r)return l;
     80     down(k);
     81     if (2*f[R]>D)return find(R,mid+1,r);
     82     return find(L,l,mid);
     83 }
     84 ll query(int k,int l,int r,int x,int y){
     85     if ((l>y)||(x>r))return 0;
     86     if ((x<=l)&&(r<=y))return sum[k];
     87     down(k);
     88     return query(L,l,mid,x,y)+query(R,mid+1,r,x,y);
     89 }
     90 ll query(int k){
     91     ll ans=0;
     92     while (k){
     93         ans+=query(1,1,n,dfn[top[k]],dfn[k]);
     94         k=fa[top[k]];
     95     }
     96     return ans;
     97 }
     98 ll calc(int k){
     99     return ans+1LL*D*dep[k]-2*query(k);
    100 }
    101 int main(){
    102     scanf("%d%d",&n,&m);
    103     memset(head,-1,sizeof(head));
    104     for(int i=1;i<n;i++){
    105         scanf("%d%d%d",&x,&y,&z);
    106         add(x,y,z);
    107         add(y,x,z);
    108     }
    109     dfs1(1,0,0);
    110     dfs2(1,0,1);
    111     build(1,1,n);
    112     for(int i=1;i<=m;i++){
    113         scanf("%d%d",&x,&y);
    114         D+=y;
    115         ans+=1LL*dep[x]*y;
    116         update(x,y);
    117         printf("%lld
    ",calc(idfn[find(1,1,n)]));
    118     }
    119 }
    View Code
  • 相关阅读:
    ZeptoLab Code Rush 2015
    UVa 10048 Audiophobia【Floyd】
    POJ 1847 Tram【Floyd】
    UVa 247 Calling Circles【传递闭包】
    UVa 1395 Slim Span【最小生成树】
    HDU 4006 The kth great number【优先队列】
    UVa 674 Coin Change【记忆化搜索】
    UVa 10285 Longest Run on a Snowboard【记忆化搜索】
    【NOIP2016提高A组模拟9.28】求导
    【NOIP2012模拟10.9】电费结算
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14641249.html
Copyright © 2011-2022 走看看