zoukankan      html  css  js  c++  java
  • suoi63 树与路径 (倍增lca)

    发现对于某一个点它向上发的一条边,它被经过的次数就是这个点子树数量*不是它子树的数量

    那就维护一个前缀和,然后每次拿两个端点和它们的lca的值加一加减一减,再乘上加上的值,就是这次修改后答案的增量

    (最后答案还要除以(N*N))

    倍增会被卡空间,难受

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define lowb(x) ((x)&(-(x)))
     4 #define REP(i,n0,n) for(i=n0;i<=n;i++)
     5 #define PER(i,n0,n) for(i=n;i>=n0;i--)
     6 #define MAX(a,b) ((a>b)?a:b)
     7 #define MIN(a,b) ((a<b)?a:b)
     8 #define CLR(a,x) memset(a,x,sizeof(a))
     9 #define rei register int
    10 using namespace std;
    11 typedef long long ll;
    12 const int maxn=1000010,mod=998244353;
    13 
    14 inline ll rd(){
    15     ll x=0;char c=getchar();int neg=1;
    16     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    17     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    18     return x*neg;
    19 }
    20 
    21 struct Edge{
    22     int a,b,l,ne;
    23 }eg[maxn*2];
    24 int N,M,egh[maxn],ect,lg[maxn],NP;
    25 int fa[maxn][2],dep[maxn],siz[maxn],sum[maxn],num[maxn],ans;
    26 
    27 inline void adeg(int a,int b,int l){
    28     eg[++ect].a=a;eg[ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
    29 }
    30 
    31 void dfs(int x,int f){
    32     fa[x][0]=f;siz[x]=1;dep[x]=dep[f]+1;
    33     for(int i=0;fa[i]&&fa[fa[x][i]][i];i++) fa[x][i+1]=fa[fa[x][i]][i];
    34     for(int i=egh[x];i!=-1;i=eg[i].ne){
    35         if(eg[i].b==f) continue;
    36         dfs(eg[i].b,x);siz[x]+=siz[eg[i].b];
    37     }num[x]=1LL*siz[x]*(N-siz[x])%mod;
    38 }
    39 void dfs2(int x,int f){
    40     sum[x]=(sum[f]+num[x])%mod;
    41     for(int i=egh[x];i!=-1;i=eg[i].ne){
    42         if(eg[i].b==f) continue;
    43         dfs2(eg[i].b,x);
    44     }
    45 }
    46 
    47 inline int modp(int x,int p){
    48     int re=1;
    49     while(p){
    50         if(p&1) re=1LL*re*x%mod;
    51         x=1LL*x*x%mod;p>>=1;
    52     }return re;
    53 }
    54 
    55 inline int lca(int x,int y){
    56     if(dep[x]<dep[y]) swap(x,y);
    57     while(dep[x]!=dep[y]){
    58         x=fa[x][lg[dep[x]-dep[y]]];
    59     }if(x==y) return x;
    60     for(int i=lg[dep[x]];i>=0;i--){
    61         if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    62     }return fa[x][0];
    63 }
    64 
    65 int main(){
    66     //freopen("su63.in","r",stdin);
    67     rei i,j,k;
    68     N=rd(),M=rd();CLR(egh,-1);NP=modp(1LL*N*N,mod-2);
    69     for(i=1,j=0,k=2;i<=N;i++){
    70         if(i>=k) j++,k<<=1;lg[i]=j;
    71     }
    72     REP(i,1,N-1){
    73         int a=rd(),b=rd(),c=rd();
    74         adeg(a,b,c);adeg(b,a,c);
    75     }dfs(1,0);dfs2(1,0);
    76     int ans=0;
    77     for(i=1;i<=ect;i++){
    78         int a=eg[i].a,b=eg[i].b;
    79         ans=(1LL*num[dep[a]>dep[b]?a:b]*eg[i].l+ans)%mod;
    80     }printf("%d
    ",(int)(1LL*ans*NP%mod));
    81     REP(i,1,M){
    82         int a=rd(),b=rd();ll c=rd();
    83         j=lca(a,b);//printf("%d %d %d %d %d %d
    ",a,b,j,num[a],num[b],num[j]);
    84         ans=((c*2*(sum[a]+sum[b]-sum[j]*2)+ans)%mod+mod)%mod;
    85         printf("%d
    ",(int)(1LL*ans*NP%mod));
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    java foreach遍历的前提条件
    Java中的null值总结
    mybatis不可忽略的细节
    设计模式:创建型模式
    设计模式(四):原型模式
    设计模式(三):建造者模式
    设计模式(二):单例模式(DCL及解决办法)
    设计模式(一):简单工厂、工厂模式、抽象工厂
    定时任务 ScheduledExecutorService
    快速访问GitHub
  • 原文地址:https://www.cnblogs.com/Ressed/p/9643898.html
Copyright © 2011-2022 走看看