zoukankan      html  css  js  c++  java
  • [CF1192B]动态直径

    题意

    给一棵固定形态的树,边有边权,每次修改一条边权,在线求出修改后树的直径。


    思考

    写出树的全dfs序。生成方式为:每当一个点进栈或入栈时,记录它的编号。

    考虑这个dfs序上两点之间的距离。设某个节点在dfs序中第一次出现的位置为$where_i$,第i个位置的节点为$what_i$两个点分别为u和v。可以发现,在dfs上,u和v之间一堆会包含它们的lca,则:

    $$dis_{u,v}=max_{where_u leq x leq where_v}{{dep_u+dep_v-2*dep_{what_x}}}$$

    树的直径即为上述表达式的最大值。

    考虑到直径的形式为u-lca-v的形式,我们可以在dfs序上看成是L、M、R的这三部分组成,其中L和R要尽可能大,M要尽可能小(代码中先加了符号,所以还是最大的)。考虑线段树,维护当前区间的最大值、M、LM、MR和LMR,最后的答案即为线段树根节点的LMR。不难证明,可以进行如下合并:
    $val=max{{val_l,val_r}}$

    $M=max{{M_l,M_r}}$(取了负号)
    $LM=max{{LM_l,LM_r,val_l+M_r}}$
    $MR=max{{RM_l,RM_r,M_l+val_r}}$

    $LMR=max{{LMR_l,LMR_r,LM_l+val_r,val_l+RM_r}}$

    对于修改操作,相当于是区间修改,直接打标记即可。

    时间复杂度:$O(n+qlogn)$


    代码

      1 // luogu-judger-enable-o2
      2 #include<bits/stdc++.h>
      3 using namespace std;
      4 const int maxn=1E5+5;
      5 typedef long long int ll;
      6 int n,m;
      7 int size=1,head[maxn*2];
      8 int dfn,dfnFirst[maxn],dfnLast[maxn],what[maxn*2],fa[maxn];
      9 ll lastans,weight[maxn],dep[maxn];
     10 ll val[maxn*8],M[maxn*8],LM[maxn*8],MR[maxn*8],LMR[maxn*8],tag[maxn*8];
     11 struct edge
     12 {
     13     int to,next;
     14     ll w;
     15 }E[maxn*2];
     16 inline void addE(int u,int v,ll w)
     17 {
     18     E[++size].to=v;
     19     E[size].next=head[u];
     20     E[size].w=w;
     21     head[u]=size;
     22 }
     23 void dfs(int u,int F,ll d)
     24 {
     25     what[dfnFirst[u]=++dfn]=u;
     26     dep[u]=d;
     27     fa[u]=F;
     28     for(int i=head[u];i;i=E[i].next)
     29     {
     30         int v=E[i].to;
     31         if(v==F)
     32             continue;
     33         weight[v]=E[i].w;
     34         dfs(v,u,d+E[i].w);
     35         what[++dfn]=u;
     36     }
     37     dfnLast[u]=dfn;
     38 }
     39 inline void pushdown(int l,int r,int num)
     40 {
     41     val[num]+=tag[num];
     42     M[num]-=tag[num]*2;
     43     LM[num]-=tag[num];
     44     MR[num]-=tag[num];
     45     if(l!=r)
     46         tag[num<<1]+=tag[num],tag[num<<1|1]+=tag[num];
     47     tag[num]=0;
     48 }
     49 inline void update(int l,int r,int num)
     50 {
     51     if(l==r)
     52         return;
     53     val[num]=max(val[num<<1],val[num<<1|1]);
     54     M[num]=max(M[num<<1],M[num<<1|1]);
     55     LM[num]=max(max(LM[num<<1],LM[num<<1|1]),val[num<<1]+M[num<<1|1]);
     56     MR[num]=max(max(MR[num<<1],MR[num<<1|1]),M[num<<1]+val[num<<1|1]);
     57     LMR[num]=max(max(LMR[num<<1],LMR[num<<1|1]),max(LM[num<<1]+val[num<<1|1],val[num<<1]+MR[num<<1|1]));
     58 }
     59 void build(int l,int r,int num)
     60 {
     61     if(l==r)
     62     {
     63         int pos=what[l];
     64         val[num]=dep[pos];
     65         M[num]=-2*dep[pos];
     66         LM[num]=MR[num]=-dep[pos];
     67         return;
     68     }
     69     int mid=(l+r)>>1;
     70     build(l,mid,num<<1),build(mid+1,r,num<<1|1);
     71     update(l,r,num);
     72 }
     73 void add(int L,int R,int l,int r,ll x,int num)
     74 {
     75     if(L<=l&&r<=R)
     76     {
     77         tag[num]+=x;
     78         pushdown(l,r,num);
     79         return;
     80     }
     81     pushdown(l,r,num);
     82     int mid=(l+r)>>1;
     83     if(R<=mid)
     84         add(L,R,l,mid,x,num<<1);
     85     else if(mid<L)
     86         add(L,R,mid+1,r,x,num<<1|1);
     87     else
     88         add(L,R,l,mid,x,num<<1),add(L,R,mid+1,r,x,num<<1|1);
     89     pushdown(l,mid,num<<1);
     90     pushdown(mid+1,r,num<<1|1);
     91     update(l,r,num);
     92 }
     93 int main()
     94 {
     95     ios::sync_with_stdio(false);
     96     ll W;
     97     cin>>n>>m>>W;
     98     for(int i=2;i<=n;++i)
     99     {
    100         int x,y;
    101         ll z;
    102         cin>>x>>y>>z;
    103         addE(x,y,z);
    104         addE(y,x,z);
    105     }
    106     dfs(1,1,0);
    107     build(1,2*n-1,1);
    108     while(m--)
    109     {
    110         ll x,y;
    111         cin>>x>>y;
    112         x=(x+lastans)%(n-1)+1;
    113         y=(y+lastans)%W;
    114         if(fa[E[x<<1].to]==E[x<<1|1].to)
    115             x=E[x<<1].to;
    116         else
    117             x=E[x<<1|1].to;
    118         add(dfnFirst[x],dfnLast[x],1,2*n-1,y-weight[x],1);
    119         weight[x]=y;
    120         lastans=LMR[1];
    121         cout<<lastans<<endl;
    122     }
    123     return 0;
    124 }
    View Code
  • 相关阅读:
    HDU 5671 矩阵
    HDU 5670
    UVA 11995 STL 使用
    VK Cup 2016
    字段定义
    apache用户
    apache
    使用第三方登录
    setex()
    如果客户端禁用了cookie,如何实现session
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11409292.html
Copyright © 2011-2022 走看看