原文链接https://www.cnblogs.com/zhouzhendong/p/CC-FIBTREE.html

题目传送门 - CC-FIBTREE

题意

  给定一个有 $n$ 个节点,初始点权都为 $0$ 的无根树。

  现在让你处理 $m$ 次操作,有下面 $4$ 种类型。

  1.  链上加斐波那契数列,其中 $f[1]=1,f[2]=1,f[3]=2,\cdots$

  2.  链上求和

  3.  给定树根,子树求和

  4.  回到第 $x$ 次询问时的状态。

  强制在线。答案对于 $10^9+9$ 取模。

  $n,m\leq 10^5$

题解

  这大概又是一道我从去年留到今年的为数不多的坑。终于填掉了。

  这次两个错误找了半天: 1. query 在子区间结果相加的时候忘记取模 2. 忘记考虑第三种操作中 $x=y$ 的情况。

  下面讲算法。

  首先我们来把斐波那契数列搞定。

  矩阵乘法当然可以,但是麻烦、常数大。

  首先我们找到斐波那契数列的通项公式:

$$f_i=\cfrac{\left(\cfrac{1+\sqrt{5}}{2}\right)^n-\left(\cfrac{1-\sqrt{5}}{2}\right)^n}{\sqrt{5}}$$

  我们可以暴力跑出来,在模 $10^9+9$ 意义下,有两个数满足 $ i^2\equiv 5 \pmod{10^9+9}$ 。

  这里我们取 $\sqrt{5}\equiv 383008016 \pmod{10^9+9}$ 。

  则:

  $\cfrac{\sqrt{5}}{5}\equiv 276601605 \pmod{10^9+9}$

  $\cfrac{1+\sqrt{5}}{2}\equiv 691504013 \pmod{10^9+9}$

  $\cfrac{1-\sqrt{5}}{2}\equiv 308495997 \pmod{10^9+9}$

  所以,

$$f_i\equiv 276601605\times(691504013^{\ n}-308495997^{\ n})\pmod{10^9+9}$$

  于是我们成功把链上加斐波那契数列变成了链上加等比数列。

  两个方向,两个公比,至少维护 $4$ 个量了。

  树链修改,我们只需要树链剖分一下就可以了。

  树链询问,通过树剖直接搞。

  子树询问,由于我们要树剖,我们先会定根,但是这个询问的根是 $x$,子树是 $y$  ,不是我们定的,所以我们要分三种情况考虑一下。

  1.  $y=x$  那么显然答案就是所有的 $n$ 个节点权值和。

  2.  $y\neq x$ 且 $y$ 是 $x$ 的祖先  那么答案就是整棵树的权值和减去 $y$ 连向 $x$ 的那棵子树权值和。

  3.  $y\neq x$ 且 $y$ 不是 $x$ 的祖先  那么答案显然就是 $y$ 这棵子树的答案

  至于第四种操作,那么就是要你强行写可持久化,写主席树。

  由于要写主席树,如果写下传的懒标记会很难写,所以我们采用标记永久化。

  具体标记永久化方法看代码,这里不多加赘述。

  代码很长,请慎重选择是否开做此题,谨防挖坑。

代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int N=100005,S=N*200,mod=1e9+9;
  5. struct Gragh{
  6. static const int M=N*2;
  7. int cnt,y[M],nxt[M],fst[N];
  8. void clear(){cnt=0;memset(fst,0,sizeof fst);}
  9. void add(int a,int b){y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;}
  10. }g;
  11. int Pow(int x,int y){
  12. int ans=1;
  13. for (;y;y>>=1,x=1LL*x*x%mod)
  14. if (y&1)
  15. ans=1LL*ans*x%mod;
  16. return 0;
  17. }
  18. int n,m,V=276601605,V1=691504013,V2=308495997;
  19. int Pow1[N],Pow2[N],Sum1[N],Sum2[N];
  20. int size[N],depth[N],son[N],fa[N][20],in[N],out[N],top[N],p[N],ap[N],Time=0,cnp=0;
  21. void Get_Gen_Info(int x,int pre,int d){
  22. size[x]=1,son[x]=-1,depth[x]=d,fa[x][0]=pre;
  23. for (int i=1;i<20;i++)
  24. fa[x][i]=fa[fa[x][i-1]][i-1];
  25. for (int i=g.fst[x];i;i=g.nxt[i])
  26. if (g.y[i]!=pre){
  27. int y=g.y[i];
  28. Get_Gen_Info(y,x,d+1);
  29. size[x]+=size[y];
  30. if (son[x]==-1||size[y]>size[son[x]])
  31. son[x]=y;
  32. }
  33. }
  34. void Get_Top(int x,int Top){
  35. in[x]=++Time,ap[p[x]=++cnp]=x,top[x]=Top;
  36. if (son[x]!=-1)
  37. Get_Top(son[x],Top);
  38. for (int i=g.fst[x];i;i=g.nxt[i]){
  39. int y=g.y[i];
  40. if (y!=son[x]&&y!=fa[x][0])
  41. Get_Top(y,y);
  42. }
  43. out[x]=Time;
  44. }
  45. struct Seg{
  46. int sum,L1,L2,R1,R2,ls,rs,len;
  47. int TagV(){return (1LL*(L1+R1)*Sum1[len-1]-1LL*(L2+R2)*Sum2[len-1]+sum)%mod;}
  48. }T[S];
  49. int root[N],tot=0;
  50. int build(int L,int R){
  51. int rt=++tot;
  52. T[rt].len=R-L+1;
  53. if (L==R)
  54. return rt;
  55. int mid=(L+R)>>1;
  56. T[rt].ls=build(L,mid);
  57. T[rt].rs=build(mid+1,R);
  58. return rt;
  59. }
  60. void update(int prt,int &rt,int L,int R,int xL,int xR,int type,int Lv,int Rv){
  61. if (rt==0)
  62. rt=prt;
  63. if (L>xR||R<xL)
  64. return;
  65. if (rt==prt)
  66. T[rt=++tot]=T[prt];
  67. if (xL<=L&&R<=xR){
  68. if (type==0)
  69. T[rt].L1=(T[rt].L1+Pow1[Lv])%mod,T[rt].L2=(T[rt].L2+Pow2[Lv])%mod;
  70. else
  71. T[rt].R1=(T[rt].R1+Pow1[Rv])%mod,T[rt].R2=(T[rt].R2+Pow2[Rv])%mod;
  72. return;
  73. }
  74. int mid=(L+R)>>1,lenL=mid-L+1,lenR=R-mid;
  75. update(T[prt].ls,T[rt].ls,L,mid,xL,xR,type,Lv,Rv+lenR);
  76. update(T[prt].rs,T[rt].rs,mid+1,R,xL,xR,type,Lv+lenL,Rv);
  77. T[rt].sum=(T[T[rt].ls].TagV()+T[T[rt].rs].TagV())%mod;
  78. }
  79. int query(int rt,int L,int R,int xL,int xR,int L1,int L2,int R1,int R2){
  80. if (L>xR||R<xL)
  81. return 0;
  82. L1=(L1+T[rt].L1)%mod,L2=(L2+T[rt].L2)%mod;
  83. R1=(R1+T[rt].R1)%mod,R2=(R2+T[rt].R2)%mod;
  84. if (xL<=L&&R<=xR){
  85. int res=T[rt].sum;
  86. res=(1LL*(L1+R1)*Sum1[T[rt].len-1]-1LL*(L2+R2)*Sum2[T[rt].len-1]+res)%mod;
  87. res=(res+mod)%mod;
  88. return res;
  89. }
  90. int mid=(L+R)>>1,lenL=mid-L+1,lenR=R-mid;
  91. return (query(T[rt].ls,L,mid,xL,xR,L1,L2,1LL*R1*Pow1[lenR]%mod,1LL*R2*Pow2[lenR]%mod)
  92. +query(T[rt].rs,mid+1,R,xL,xR,1LL*L1*Pow1[lenL]%mod,1LL*L2*Pow2[lenL]%mod,R1,R2))%mod;
  93. }
  94. int LCA(int x,int y){
  95. if (depth[x]<depth[y])
  96. swap(x,y);
  97. for (int i=19;i>=0;i--)
  98. if (depth[x]-(1<<i)>=depth[y])
  99. x=fa[x][i];
  100. if (x==y)
  101. return x;
  102. for (int i=19;i>=0;i--)
  103. if (fa[x][i]!=fa[y][i])
  104. x=fa[x][i],y=fa[y][i];
  105. return fa[x][0];
  106. }
  107. void Tupdate(int prt,int &rt,int x,int y){
  108. int Fx=top[x],Fy=top[y],Tx=0,Ty=0;
  109. int lca=LCA(x,y),len=depth[x]+depth[y]-depth[lca]*2+1;
  110. while (Fx!=Fy)
  111. if (depth[Fx]>depth[Fy]){
  112. update(prt,rt,1,n,p[Fx],p[x],1,0,Tx+1-(n-p[x]));
  113. Tx+=depth[x]-depth[Fx]+1;
  114. x=fa[Fx][0],Fx=top[x];
  115. }
  116. else {
  117. Ty+=depth[y]-depth[Fy]+1;
  118. update(prt,rt,1,n,p[Fy],p[y],0,len-Ty+1-(p[Fy]-1),0);
  119. y=fa[Fy][0],Fy=top[y];
  120. }
  121. if (depth[x]<depth[y])
  122. update(prt,rt,1,n,p[x],p[y],0,Tx+1-(p[x]-1),0);
  123. else
  124. update(prt,rt,1,n,p[y],p[x],1,0,Tx+1-(n-p[x]));
  125. }
  126. int Tquery(int rt,int x,int y){
  127. int Fx=top[x],Fy=top[y];
  128. int ans=0;
  129. while (Fx!=Fy){
  130. if (depth[Fx]<depth[Fy])
  131. swap(x,y),swap(Fx,Fy);
  132. ans=(ans+query(rt,1,n,p[Fx],p[x],0,0,0,0))%mod;
  133. x=fa[Fx][0],Fx=top[x];
  134. }
  135. if (depth[x]>depth[y])
  136. swap(x,y);
  137. ans=(ans+query(rt,1,n,p[x],p[y],0,0,0,0))%mod;
  138. return ans;
  139. }
  140. int main(){
  141. scanf("%d%d",&n,&m);
  142. Pow1[0]=Pow2[0]=1,Sum1[0]=Sum2[0]=1;
  143. for (int i=1;i<=n;i++){
  144. Pow1[i]=1LL*Pow1[i-1]*V1%mod,Sum1[i]=(Sum1[i-1]+Pow1[i])%mod;
  145. Pow2[i]=1LL*Pow2[i-1]*V2%mod,Sum2[i]=(Sum2[i-1]+Pow2[i])%mod;
  146. }
  147. g.clear();
  148. for (int i=1,a,b;i<n;i++){
  149. scanf("%d%d",&a,&b);
  150. g.add(a,b);
  151. g.add(b,a);
  152. }
  153. Get_Gen_Info(1,0,0);
  154. Get_Top(1,1);
  155. memset(T,0,sizeof T);
  156. root[0]=build(1,n);
  157. int LASTANS=0;
  158. for (int i=1;i<=m;i++){
  159. char opt[5];
  160. int x,y;
  161. scanf("%s%d",opt+1,&x);
  162. x^=LASTANS;
  163. root[i]=root[i-1];
  164. if (opt[1]=='A'){
  165. scanf("%d",&y);
  166. Tupdate(root[i-1],root[i],x,y);
  167. }
  168. if (opt[1]=='R')
  169. root[i]=root[x];
  170. if (opt[1]=='Q'&&opt[2]=='S'){
  171. scanf("%d",&y);
  172. if (x==y){
  173. LASTANS=query(root[i],1,n,1,n,0,0,0,0);
  174. LASTANS=(1LL*LASTANS*V%mod+mod)%mod;
  175. printf("%d\n",LASTANS);
  176. }
  177. else if (in[y]<=in[x]&&out[x]<=out[y]){
  178. for (int j=19;j>=0;j--)
  179. if (depth[x]-(1<<j)>depth[y])
  180. x=fa[x][j];
  181. LASTANS=query(root[i],1,n,1,n,0,0,0,0)-query(root[i],1,n,in[x],out[x],0,0,0,0);
  182. LASTANS=(1LL*LASTANS*V%mod+mod)%mod;
  183. printf("%d\n",LASTANS);
  184. }
  185. else {
  186. LASTANS=query(root[i],1,n,in[y],out[y],0,0,0,0);
  187. LASTANS=(1LL*LASTANS*V%mod+mod)%mod;
  188. printf("%d\n",LASTANS);
  189. }
  190. }
  191. if (opt[1]=='Q'&&opt[2]=='C'){
  192. scanf("%d",&y);
  193. LASTANS=Tquery(root[i],x,y);
  194. LASTANS=(1LL*LASTANS*V%mod+mod)%mod;
  195. printf("%d\n",LASTANS);
  196. }
  197. }
  198. return 0;
  199. }

  

Codechef FIBTREE 树链剖分 主席树 LCA 二次剩余 快速幂的更多相关文章

  1. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  2. [GDOI2016][树链剖分+主席树]疯狂动物城

    题面 Description Nick 是只在动物城以坑蒙拐骗为生的狐狸,儿时受到偏见的伤害,放弃了自己的理想.他被兔子 Judy 设下圈套,被迫与她合作查案,而卷入意想不到的阴谋,历尽艰险后成为搭档 ...

  3. HDU 5111 Alexandra and Two Trees 树链剖分 + 主席树

    题意: 给出两棵树,每棵树的节点都有一个权值. 同一棵树上的节点的权值互不相同,不同树上节点的权值可以相同. 要求回答如下询问: \(u_1 \, v_1 \, u_2 \, v_2\):询问第一棵树 ...

  4. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  5. bzoj 4448 [Scoi2015]情报传递 (树链剖分+主席树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4448 题面: Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络 ...

  6. BZOJ 4448: [Scoi2015]情报传递 树链剖分 主席树

    4448: [Scoi2015]情报传递 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4448 Description 奈特公司是一个巨 ...

  7. BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树

    题意:给定一棵树,树上每个点有权值和类型.支持:修改某个点的类型:修改某个点的权值:询问某条链上某个类型的点的和/最大值.点数/类型数/询问数<=100000. 分析: 树链剖分,对每个类型的点 ...

  8. 5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治

    LINK:小V和gcd树 时限是8s 所以当时好多nq的暴力都能跑过. 考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过. 不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nq ...

  9. BZOJ4012 HNOI2015开店(树链剖分+主席树)

    考虑这样一个问题:一棵树初始全是白点,有两种操作:把一个点染黑:询问某点到所有黑点的距离之和. 注意到树上两点x和y的距离为depth[x]+depth[y]-depth[lca(x,y)]*2.要求 ...

随机推荐

  1. Laravel资源理由器跟隐式控制的对比及是怎样的吧?- Route::resource vs Route::controller

    stackoverflow找到的问题:http://stackoverflow.com/questions/23505875/laravel-routeresource-vs-routecontrol ...

  2. js基础学习

  3. C3盒子弹性布局

    有效的对一个容器中的子元素进行排列.对齐和分配空白空间. 对浏览器版本要求较高,多用于移动端的响应式设计 flex-direction 顺序指定了弹性子元素在父容器中的位置. flex-directi ...

  4. RianbowDesign

    换了很多个名字,最后换成这个. 主要考虑把自己所学的.所经历的都结合到一起,用这种方式来保持热情. 算是一个设计网站,管理咨询,游戏设计,平面logo之类,想最多地攘括到里边.就像自己不确定的主业一样 ...

  5. Confluence 6 生产环境备份策略

    如果你是下面的情况,Confluence 的自动每日 XML 备份可能适合你: 正在评估使用 Confluence 你对数据库的管理并不是非常熟悉同时你的 Confluence 安装实例的数据量并不大 ...

  6. lightoj1336 约数和

    /*sigma(n)的每一项都可以看成是个pi的[0,ei]等比数列求和公式,那么sigma(n)就是n所有正约数的和要求找到sigma(x)为奇数的个数1<=x<=n */ 看题解的.. ...

  7. Nginx详解二十五:Nginx架构篇之Nginx常见的问题

    Nginx常见的问题 1.相同server_name多个虚拟主机优先级访问,是按读取文件的优先级来排序 在/opt/app/下准备3个code文件夹,下面放入3个html文件,里面的内容分别是code ...

  8. Mac下Java JDK的下载安装和配置

    一.下载安装 打开一个搜索引擎,输入JDK,找到Java JDK 如图:  点击打开,同意协议开始下载如图: 下载好以后,安装即可. 安装成功以后,进入根目录,可以找到JDK安装的位置: 资源库——& ...

  9. add web server(nginx)

    #!/bin/bash # # Web Server Install Script # Last Updated 2012.09.24 # ##### modify by WanJie 2012.09 ...

  10. springcloud Eureka控制台参数说明

    Home进入Eureka控制台首页,首先看HOME页的头部 System Status Environment : 环境,默认为test, 该参数在实际使用过程中,可以不用更改 Data center ...