这是一道巨题,我已无力吐槽为什么我怎么写都不过

我们对于这种无修改的边权题目有一个经典的树上差分套路:

\(ans=sum_x+sum_y-2\cdot sum_{LCA(x,y)}\)

这里的\(sum\)表示的是从根到这个点的边权前缀和

然后这里求的是点权,我们还是用一样的策略,就是树上查分后加上这个点的点权即可,即:

\(ans=sum_x+sum_y-2\cdot sum_{LCA(x,y)}+node_{LCA(x,y)}\)

然后我们发现\(1\le k\le 50\),所以我们预处理出所有的幂次的情况然后LCA查找即可。

然后就我就先写了我比较熟悉的DFS序+RMQ,然后蜜汁RE90pts

DFS序+RMQ CODE

  1. // luogu-judger-enable-o2
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. using namespace std;
  6. typedef long long LL;
  7. const LL N=300005,P=25,mod=998244353;
  8. struct edge
  9. {
  10. LL to,next;
  11. }e[N<<1];
  12. struct RMQ
  13. {
  14. LL x,num;
  15. }f[N<<1][P];
  16. LL head[N],dep[N],fir[N],n,m,k,cnt,tot,x,y,rt=1,s[N][55],node[N][55];
  17. inline char tc(void)
  18. {
  19. static char fl[100000],*A=fl,*B=fl;
  20. return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
  21. }
  22. inline void read(LL &x)
  23. {
  24. x=0; char ch=tc();
  25. while (ch<'0'||ch>'9') ch=tc();
  26. while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
  27. }
  28. inline void write(LL x)
  29. {
  30. if (x/10) write(x/10);
  31. putchar(x%10+'0');
  32. }
  33. inline void add(LL x,LL y)
  34. {
  35. e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
  36. }
  37. inline void swap(LL &a,LL &b)
  38. {
  39. LL t=a; a=b; b=t;
  40. }
  41. inline void DFS(LL now,LL fa,LL d)
  42. {
  43. dep[now]=d; f[++tot][0].x=dep[now]; f[tot][0].num=now; fir[now]=tot;
  44. for (register LL i=head[now];i^-1;i=e[i].next)
  45. if (e[i].to^fa) DFS(e[i].to,now,d+1),f[++tot][0].x=dep[now],f[tot][0].num=now;
  46. }
  47. inline void reset(LL now,LL fa,LL k)
  48. {
  49. node[now][k]=(node[now][k-1]*dep[now])%mod; s[now][k]=(s[now][k]+node[now][k])%mod;;
  50. for (register LL i=head[now];i^-1;i=e[i].next)
  51. if (e[i].to^fa) s[e[i].to][k]=(s[e[i].to][k]+s[now][k])%mod,reset(e[i].to,now,k);
  52. }
  53. inline void init(void)
  54. {
  55. for (register LL j=1;j<P;++j)
  56. for (register LL i=1;i+(1<<j)-1<=tot;++i)
  57. f[i][j]=f[i][j-1].x<f[i+(1<<j-1)][j-1].x?f[i][j-1]:f[i+(1<<j-1)][j-1];
  58. }
  59. inline LL LCA(LL x,LL y)
  60. {
  61. x=fir[x]; y=fir[y]; if (x>y) swap(x,y);
  62. LL k=(LL)log2(y-x+1);
  63. return f[x][k].x<f[y-(1<<k)+1][k].x?f[x][k].num:f[y-(1<<k)+1][k].num;
  64. }
  65. int main()
  66. {
  67. //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
  68. register LL i; read(n);
  69. memset(head,-1,sizeof(head));
  70. memset(e,-1,sizeof(e));
  71. for (i=1;i<n;++i)
  72. read(x),read(y),add(x,y),add(y,x);
  73. DFS(rt,-1,0); init();
  74. for (i=1;i<=n;++i)
  75. node[i][0]=1;
  76. for (i=1;i<=50;++i)
  77. reset(rt,-1,i); read(m);
  78. while (m--)
  79. {
  80. read(x); read(y); read(k); LL fa=LCA(x,y);
  81. write((LL)((s[x][k]+s[y][k]-(2*s[fa][k])%mod+node[fa][k])%mod+mod)%mod); putchar('\n');
  82. }
  83. return 0;
  84. }

然后我就不爽了,直接上了大力树剖,当然很不幸,树剖被Hack数据卡掉了

大力树剖CODE

  1. // luogu-judger-enable-o2
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. typedef long long LL;
  6. const int N=300005,K=55,mod=998244353;
  7. struct edge
  8. {
  9. int to,next;
  10. }e[N<<1];
  11. int n,m,rt=1,x,y,k,cnt,tot,head[N],dep[N][K],tree[N<<2][K],father[N],id[N],top[N],son[N],size[N],num[N];
  12. inline char tc(void)
  13. {
  14. static char fl[100000],*A=fl,*B=fl;
  15. return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
  16. }
  17. inline void read(int &x)
  18. {
  19. x=0; char ch=tc();
  20. while (ch<'0'||ch>'9') ch=tc();
  21. while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
  22. }
  23. inline void write(int x)
  24. {
  25. if (x/10) write(x/10);
  26. putchar(x%10+'0');
  27. }
  28. inline void add(int x,int y)
  29. {
  30. e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
  31. }
  32. inline void swap(int &a,int &b)
  33. {
  34. int t=a; a=b; b=t;
  35. }
  36. inline void build(int k,int rt,int l,int r)
  37. {
  38. if (l==r)
  39. {
  40. tree[rt][k]=dep[num[l]][k];
  41. return;
  42. }
  43. int mid=l+r>>1;
  44. build(k,rt<<1,l,mid); build(k,rt<<1|1,mid+1,r);
  45. tree[rt][k]=tree[rt<<1][k]+tree[rt<<1|1][k];
  46. if (tree[rt][k]>=mod) tree[rt][k]-=mod;
  47. }
  48. inline int query(int k,int rt,int l,int r,int beg,int end)
  49. {
  50. if (l>=beg&&r<=end) return tree[rt][k];
  51. int mid=l+r>>1,res=0;
  52. if (beg<=mid) res+=query(k,rt<<1,l,mid,beg,end);
  53. if (end>mid) res+=query(k,rt<<1|1,mid+1,r,beg,end);
  54. if (res>=mod) res-=mod; return res;
  55. }
  56. inline void DFS1(int now,int fa,int d)
  57. {
  58. dep[now][1]=d; father[now]=fa; size[now]=1; int res=-1;
  59. for (register int i=head[now];i!=-1;i=e[i].next)
  60. if (e[i].to!=fa)
  61. {
  62. DFS1(e[i].to,now,d+1);
  63. size[now]+=size[e[i].to];
  64. if (size[e[i].to]>res) res=size[e[i].to],son[now]=e[i].to;
  65. }
  66. }
  67. inline void DFS2(int now,int topf)
  68. {
  69. id[now]=++tot; num[tot]=now; top[now]=topf;
  70. if (!son[now]) return; DFS2(son[now],topf);
  71. for (register int i=head[now];i!=-1;i=e[i].next)
  72. if (e[i].to!=father[now]&&e[i].to!=son[now]) DFS2(e[i].to,e[i].to);
  73. }
  74. inline void init(void)
  75. {
  76. for (register int i=1;i<=50;++i)
  77. {
  78. for (register int j=1;j<=n&&i!=1;++j)
  79. dep[j][i]=(LL)dep[j][i-1]*dep[j][1]%mod;
  80. build(i,1,1,n);
  81. }
  82. }
  83. inline int get_sec(int k,int x,int y)
  84. {
  85. int ans=0;
  86. while (top[x]!=top[y])
  87. {
  88. if (dep[top[x]][1]<dep[top[y]][1]) swap(x,y);
  89. ans+=query(k,1,1,n,id[top[x]],id[x]);
  90. if (ans>=mod) ans-=mod; x=father[top[x]];
  91. }
  92. if (dep[x][1]<dep[y][1]) swap(x,y);
  93. ans+=query(k,1,1,n,id[y],id[x]);
  94. if (ans>=mod) ans-=mod; return ans;
  95. }
  96. int main()
  97. {
  98. //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
  99. register int i; read(n);
  100. memset(head,-1,sizeof(head));
  101. memset(e,-1,sizeof(e));
  102. for (i=1;i<n;++i)
  103. read(x),read(y),add(x,y),add(y,x);
  104. DFS1(rt,-1,0); DFS2(rt,rt); init(); read(m);
  105. while (m--)
  106. {
  107. read(x); read(y); read(k);
  108. write(get_sec(k,x,y)); putchar('\n');
  109. }
  110. return 0;
  111. }

虽然100pts了,但是不解为什么过不了Hack数据。

算了不管明天用倍增这个传说中最稳定的算法搞一下,看看是不是我太非了。

Upt:倍增LCA不开O2轻松跑过......

我以后写LCA只用倍增!

CODE

  1. #include<cstdio>
  2. #include<cstring>
  3. using namespace std;
  4. typedef long long LL;
  5. const int N=300005,K=55,P=25,mod=998244353;
  6. struct edge
  7. {
  8. int to,next;
  9. }e[N<<1];
  10. int head[N],father[N][P],n,m,x,y,k,rt=1,cnt;
  11. LL sum[N][K],dep[N][K];
  12. inline char tc(void)
  13. {
  14. static char fl[100000],*A=fl,*B=fl;
  15. return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
  16. }
  17. inline void read(int &x)
  18. {
  19. x=0; char ch=tc();
  20. while (ch<'0'||ch>'9') ch=tc();
  21. while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
  22. }
  23. inline void write(LL x)
  24. {
  25. if (x/10) write(x/10);
  26. putchar(x%10+'0');
  27. }
  28. inline void add(int x,int y)
  29. {
  30. e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
  31. }
  32. inline void swap(int &a,int &b)
  33. {
  34. int t=a; a=b; b=t;
  35. }
  36. inline void rebuild(int now)
  37. {
  38. for (register int i=2;i<=50;++i)
  39. dep[now][i]=dep[now][i-1]*dep[now][1]%mod;
  40. for (register int i=1;i<=50;++i)
  41. sum[now][i]=(dep[now][i]+sum[father[now][0]][i])%mod;
  42. }
  43. inline void DFS(int now,int fa,int d)
  44. {
  45. father[now][0]=fa; dep[now][1]=d; rebuild(now);
  46. for (register int i=head[now];i!=-1;i=e[i].next)
  47. if (e[i].to!=fa) DFS(e[i].to,now,d+1);
  48. }
  49. inline void init(void)
  50. {
  51. for (register int j=0;j<P-1;++j)
  52. for (register int i=1;i<=n;++i)
  53. if (father[i][j]) father[i][j+1]=father[father[i][j]][j];
  54. }
  55. inline int LCA(int x,int y)
  56. {
  57. if (dep[x][1]<dep[y][1]) swap(x,y);
  58. for (register int i=P-1;i>=0;--i)
  59. if (father[x][i]&&dep[father[x][i]][1]>=dep[y][1]) x=father[x][i];
  60. if (!(x^y)) return x;
  61. for (register int i=P-1;i>=0;--i)
  62. if (father[x][i]&&father[y][i]&&father[x][i]!=father[y][i])
  63. {
  64. x=father[x][i];
  65. y=father[y][i];
  66. }
  67. return father[x][0];
  68. }
  69. int main()
  70. {
  71. //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
  72. register int i; read(n);
  73. memset(head,-1,sizeof(head));
  74. memset(e,-1,sizeof(e));
  75. for (i=1;i<n;++i)
  76. read(x),read(y),add(x,y),add(y,x);
  77. DFS(rt,0,0); init(); read(m);
  78. while (m--)
  79. {
  80. read(x); read(y); read(k);
  81. int fa=LCA(x,y);
  82. write((sum[x][k]+sum[y][k]+(LL)2*mod-sum[fa][k]-sum[father[fa][0]][k])%mod); putchar('\n');
  83. }
  84. return 0;
  85. }

Luogu P4427 [BJOI2018]求和的更多相关文章

  1. P4427 [BJOI2018]求和

    P4427 [BJOI2018]求和 同[TJOI2018]教科书般的扭曲虚空 懒得写了(雾 #include<bits/stdc++.h> #define il inline #defi ...

  2. 洛谷P4427 [BJOI2018]求和

    \(\Large\textbf{Description: } \large{一颗n个节点的树,m次询问,每次查询点i到点j的路径上所有节点点深度的k次方的和并对998244353取模(1\leq n, ...

  3. 【BZOJ5293】[BJOI2018]求和(前缀和,LCA)

    [BZOJ5293][BJOI2018]求和(前缀和,LCA) 题面 BZOJ 洛谷 题解 送分题??? 预处理一下\(k\)次方的前缀和. 然后求个\(LCA\)就做完了?... #include& ...

  4. bzoj5293: [Bjoi2018]求和

    题目链接 bzoj5293: [Bjoi2018]求和 题解 暴力 对于lca为1的好坑啊.... 代码 #include<cmath> #include<cstdio> #i ...

  5. LCA+差分【p4427】[BJOI2018]求和

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的\(k\) 次方和,而且每次的\(k\) 可能是不同的.此处节点深度的 ...

  6. BZOJ5293: [Bjoi2018]求和 树上差分

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k  次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点 ...

  7. 【刷题】BZOJ 5293 [Bjoi2018]求和

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k 次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点到 ...

  8. BZOJ5293:[BJOI2018]求和(LCA,差分)

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k  次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点 ...

  9. 【Bzoj4555】【Luogu P4091】求和(NTT)

    题面 Bzoj Luogu 题解 先来颓柿子 $$ \sum_{i=0}^n\sum_{j=0}^iS(i,j)2^jj! \\ =\sum_{j=0}^n2^jj!\sum_{i=0}^nS(i,j ...

随机推荐

  1. tab 页形式展现多张报表

    业务系统中,很多报表都是沿用之前 EXCEL 的报表样式,原来以 sheet 格式显示的表,客户在 web 端展现的时候也希望也有同样的格式,润乾在实现这种效果和 EXCEL 一样简单灵活,轻松将数据 ...

  2. Apache POI导出excel表格

    项目中我们经常用到导出功能,将数据导出以便于审查和统计等.本文主要使用Apache POI实现导出数据. POI中文文档 简介 ApachePOI是Apache软件基金会的开放源码函式库,POI提供A ...

  3. asp.net根据参数找不到记录后响应404及显示错误页

    在asp.net mvc 中,action方法里根据参数获取数据,假如获取的数据为空,为了响应404错误页,我们可以return HttpNotFound(); 但是在asp.net webform中 ...

  4. CRM 各种类型字段的 赋值 取值

    //lookupRecordEntity["new_lead"] = new EntityReference(entity.LogicalName, entity.Id); 获取时 ...

  5. Solr全文检索

    1.Solr的安装 .环境要求 jdk1.+tomcat8+solr5.5.0 .将以上的软件包上传到服务器 . 安装tomcat8(解压文件) tar -zxvf apache-tomcat-.ta ...

  6. Windows Server 2012 RS 配置IIS8.0+发布网站

    一.配置iis 8.0 IIS 8.0 是 windows server 2012 自带的服务器管理系统.相比之前版本,IIS 8.0 安装和操作都更加简单,界面也很简洁,安装也很迅速. 1. 进入w ...

  7. JS学习小结(上)

    学而时习之,不亦说乎,开启JS学习新乐章~ JS是干啥的?网页特效,它主要是实现控制结构和样式,是一种行为,有多重要,不言而喻吧,页面炫酷的资本. 1. JS输出: alert("hello ...

  8. HBase——强一致性详解

    Hbase是一个强一致性数据库,不是“最终一致性”数据库,官网给出的介绍: “Strongly consistent reads/writes: HBase is not an "event ...

  9. 一个比较全面 的web项目实战学习

    一个比较全面 的web项目实战学习:http://www.cnblogs.com/jikey/p/3613082.html

  10. XML Namespace (xmlns) 属性

    http://www.w3school.com.cn/xml/xml_namespaces.asp XML Namespace (xmlns) 属性 XML 命名空间属性被放置于元素的开始标签之中,并 ...