zoukankan      html  css  js  c++  java
  • 【BJOI2018】求和

    这是一道树链剖分/树上差分/LCA的题目……

    本来想打一遍树剖,但是被那强大的码量劝退了,于是我开始思考树上差分。

    我们先把每个点深度的k次方打一个表,之后我们因为要做减法,所以我们令vali,k表示i到1号点路径上点深度的k次方之和

    然后问题来了,我们维护的是点权和,所以我们发现直接减的话会导致lca这个点没算,所以略微改一下公式,使lca这个点也被算一次

    然后我们询问u,v,k的时候输出valu,k+valv,kvallca(u,v)valfalca(u,v)即可

    问题就是如何找lca了,这个用倍增预处理,在倍增寻找即可。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 typedef long long ll;
     7 inline int read() {
     8     int ret=0;
     9     int op=1;
    10     char c=getchar();
    11     while(c<'0'||c>'9') {if(c=='-') op=-1; c=getchar();}
    12     while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar();
    13     return ret*op;
    14 }
    15 const ll mod=998244353;
    16 struct node {
    17     int next,to;
    18 }a[300010<<1];
    19 int num,head[300010<<1];
    20 int n,m;
    21 int f[300010][25];
    22 ll d[300010];
    23 ll pow[60],val[300010][60];
    24 inline void add(int from,int to) {
    25     a[++num].next=head[from]; a[num].to=to;    head[from]=num;
    26     swap(from,to);
    27     a[++num].next=head[from]; a[num].to=to;    head[from]=num;
    28 }
    29 void dfs(int u,int fa) {
    30     for(int i=0;f[u][i];i++) f[u][i+1]=f[f[u][i]][i];
    31     for(int i=head[u];i;i=a[i].next) {
    32         int v=a[i].to;
    33         if(v==fa) continue ;
    34         f[v][0]=u;
    35         d[v]=d[u]+1;
    36         for(int j=1;j<=50;j++) pow[j]=pow[j-1]*d[v]%mod;
    37         for(int j=1;j<=50;j++) val[v][j]=(val[u][j]+pow[j])%mod;
    38         dfs(v,u);
    39     }
    40 }
    41 int lca(int x,int y) {
    42     if(d[x]<d[y]) swap(x,y);
    43     for(int i=20;i>=0;i--)
    44         if(d[f[x][i]]>=d[y]) x=f[x][i];
    45     if(x==y) return x;
    46     for(int i=20;i>=0;i--)
    47         if(f[x][i]!=f[y][i]) {
    48             x=f[x][i];
    49             y=f[y][i];
    50         }
    51     return f[x][0];
    52 }
    53 int main() {
    54     n=read();
    55     for(int i=1;i<n;i++) add(read(),read());
    56     pow[0]=1;
    57     dfs(1,0);
    58     m=read();
    59     while(m--) {
    60         ll ans=0;
    61         int i=read(),j=read(),k=read();
    62         int xx=lca(i,j);
    63         ans=val[i][k]+val[j][k]-val[xx][k]-val[f[xx][0]][k]+mod+mod;
    64         printf("%lld
    ",ans%mod);
    65     }
    66     return 0;
    67 }
    AC Code
  • 相关阅读:
    ECMAScript 6学习笔记(二):let和块级作用域
    ECMAScript 6学习笔记(一):展开运算符
    JavaScript的作用域和闭包
    HTML中行内元素的竖直方向的padding和margin是否真的无效
    <input type="text"/>未输入时属性value的默认值--js学习之路
    Matlab 之 FFT的理解和应用
    .NET 5.0实现Consul服务注册
    面向对象编程思想(OOP)
    又再回归一次
    阿里云的OCS缓存机制
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10805370.html
Copyright © 2011-2022 走看看