• [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
  • 相关阅读:
    mybatis 查询一对多子表只能查出一条数据
    Docker 查看容器里Log4写的日 志文 件里的日志
    MYSQL之union的使用
    【前端开发】常见好用的流程图框架
    【推荐】好网站推荐
    【前端工具】好用的数据库工具Navicat
    jQuery ajax
    thinkphp6.0封装数据库及缓存模型
    Unity 3D使用C#脚本实例
    Unity 3D简单使用C#脚本,脚本的执行顺序
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14641249.html
Copyright © 2020-2023  润新知