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\n",(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\n",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\n",(int)(1LL*ans*NP%mod));
86     }
87     return 0;
88 }

 

posted @ 2018-09-13 23:16  Ressed  阅读(254)  评论(0编辑  收藏  举报