看来这个LCT板子并没有什么问题

  1. #include<cstdio>
  2. #include<algorithm>
  3. using namespace std;
  4. typedef long long LL;
  5. const LL md=;
  6. namespace LCT
  7. {
  8. struct Node
  9. {
  10. Node *ch[],*fa;
  11. bool rev;
  12. LL addv,mulv;
  13. LL dat,sum,sz;
  14. void padd(LL x)
  15. {
  16. addv=(addv+x)%md;dat=(dat+x)%md;sum=(sum+x*sz)%md;
  17. }
  18. void pmul(LL x)
  19. {
  20. addv=addv*x%md;mulv=mulv*x%md;dat=dat*x%md;sum=sum*x%md;
  21. }
  22. void upd()
  23. {
  24. sum=((ch[]?ch[]->sum:)+(ch[]?ch[]->sum:)+dat)%md;
  25. sz=(ch[]?ch[]->sz:)+(ch[]?ch[]->sz:)+;
  26. }
  27. void pd()
  28. {
  29. if(rev)
  30. {
  31. swap(ch[],ch[]);
  32. if(ch[]) ch[]->rev^=;
  33. if(ch[]) ch[]->rev^=;
  34. rev=;
  35. }
  36. if(mulv!=)
  37. {
  38. if(ch[]) ch[]->pmul(mulv);
  39. if(ch[]) ch[]->pmul(mulv);
  40. mulv=;
  41. }
  42. if(addv)
  43. {
  44. if(ch[]) ch[]->padd(addv);
  45. if(ch[]) ch[]->padd(addv);
  46. addv=;
  47. }
  48. }
  49. }nodes[];
  50. LL mem;
  51. Node *getnode()
  52. {
  53. return nodes+(mem++);
  54. }
  55. bool isroot(Node *x)
  56. {
  57. return (!x->fa)||((x->fa->ch[]!=x)&&(x->fa->ch[]!=x));
  58. }
  59. bool gson(Node *o) {return o==o->fa->ch[];}//获得是父亲的左儿子(返回0)还是右儿子(1),要求保证存在父亲
  60. void rotate(Node *o,bool d)
  61. //在o子树中执行d=0左旋,d=1右旋,在旋转前不标记下传,并将o父节点的对应子节点由o变为需要值,要求保证存在子树(!d)
  62. {
  63. Node *k=o->ch[!d];if(!isroot(o)) o->fa->ch[gson(o)]=k;//注意这一句修改o父节点的要写在前面,曾经出过错调了一会
  64. o->ch[!d]=k->ch[d];k->ch[d]=o;
  65. o->upd();k->upd();
  66. k->fa=o->fa;o->fa=k;if(o->ch[!d]) o->ch[!d]->fa=o;
  67. }
  68. Node *st[];LL top;
  69. void solvetag(Node *o)
  70. {
  71. while(!isroot(o)) st[++top]=o,o=o->fa;
  72. st[++top]=o;
  73. while(top) st[top--]->pd();
  74. }
  75. void splay(Node *o)
  76. {
  77. solvetag(o);
  78. Node *fa,*fafa;bool d1,d2;
  79. while(!isroot(o))
  80. {
  81. fa=o->fa;d1=(o==fa->ch[]);
  82. if(isroot(fa)) rotate(fa,d1);
  83. else
  84. {
  85. fafa=o->fa->fa;d2=(fa==fafa->ch[]);//要保证fa不是root之后才能获取这两个值,曾错过
  86. if(d1==d2) rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去
  87. else rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去
  88. }
  89. }
  90. }
  91. void access(Node *o)
  92. {
  93. for(Node *lst=NULL;o;lst=o,o=o->fa)
  94. {
  95. splay(o);//此处不pushdown是由于splay中保证进行过了
  96. o->ch[]=lst;o->upd();//注意upd
  97. }
  98. }
  99. Node *gtop(Node *o)
  100. {
  101. access(o);splay(o);
  102. for(;o->ch[];o=o->ch[],o->pd());//此处不在开始前pushdown(o)是由于splay中保证进行过了
  103. splay(o);return o;//听说这里不splay一下也很难卡掉
  104. }
  105. void mtop(Node *o) {access(o);splay(o);o->rev^=;}
  106. void link(Node *x,Node *y)
  107. {
  108. if(gtop(x)==gtop(y)) return;
  109. mtop(y);y->fa=x;
  110. }
  111. void cut(Node *x,Node *y)
  112. {
  113. mtop(x);access(y);splay(y);
  114. if(y->ch[]!=x||x->ch[]) return;//如果x、y之间直接有边,那么上面一行的操作之后应当是x与y在单独一棵splay中,那么一定保证y左子节点是x且x没有右子节点
  115. x->fa=y->ch[]=NULL;//注意,改的是x的父亲和y的子节点(虽然x的确是树的根,但是此时在splay上是y的子节点,不能搞混)
  116. y->upd();//注意
  117. }
  118. LL query(Node *x,Node *y)
  119. {
  120. mtop(x);access(y);splay(y);
  121. //if(gtop(y)!=x) return 0;//此题保证x与y连通,不需要
  122. return y->sum;
  123. }
  124. void add(Node *x,Node *y,LL t)
  125. {
  126. mtop(x);access(y);splay(y);
  127. y->padd(t);
  128. }
  129. void mul(Node *x,Node *y,LL t)
  130. {
  131. mtop(x);access(y);splay(y);
  132. y->pmul(t);
  133. }
  134. }
  135. LCT::Node *nd[];
  136. LL n,q;char tmp[];
  137. int main()
  138. {
  139. LL i,x,y,t,x2,y2;
  140. scanf("%lld%lld",&n,&q);
  141. for(i=;i<=n;i++)
  142. {
  143. nd[i]=LCT::getnode();
  144. nd[i]->mulv=;nd[i]->dat=nd[i]->sum=;nd[i]->sz=;
  145. }
  146. for(i=;i<n;i++)
  147. {
  148. scanf("%lld%lld",&x,&y);
  149. LCT::link(nd[x],nd[y]);
  150. }
  151. while(q--)
  152. {
  153. scanf("%s",tmp);
  154. switch(tmp[])
  155. {
  156. case '+':
  157. scanf("%lld%lld%lld",&x,&y,&t);
  158. LCT::add(nd[x],nd[y],t);
  159. break;
  160. case '-':
  161. scanf("%lld%lld%lld%lld",&x,&y,&x2,&y2);
  162. LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
  163. break;
  164. case '*':
  165. scanf("%lld%lld%lld",&x,&y,&t);
  166. LCT::mul(nd[x],nd[y],t);
  167. break;
  168. case '/':
  169. scanf("%lld%lld",&x,&y);
  170. printf("%lld\n",LCT::query(nd[x],nd[y]));
  171. }
  172. }
  173. return ;
  174. }

压行后:

  1. #pragma GCC optimize("Ofast")
  2. #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
  3. #pragma GCC diagnostic error "-fwhole-program"
  4. #pragma GCC diagnostic error "-fcse-skip-blocks"
  5. #pragma GCC diagnostic error "-funsafe-loop-optimizations"
  6. #pragma GCC diagnostic error "-std=c++14"
  7. #include<cstdio>
  8. #include<algorithm>
  9. using namespace std;
  10. typedef long long LL;
  11. const LL md=;
  12. namespace LCT
  13. {
  14. struct Node
  15. {
  16. Node *ch[],*fa;
  17. bool rev;
  18. LL addv,mulv;
  19. LL dat,sum,sz;
  20. void padd(LL x)
  21. {
  22. addv=(addv+x)%md;dat=(dat+x)%md;sum=(sum+x*sz)%md;
  23. }
  24. void pmul(LL x)
  25. {
  26. addv=addv*x%md;mulv=mulv*x%md;dat=dat*x%md;sum=sum*x%md;
  27. }
  28. void upd()
  29. {
  30. sum=((ch[]?ch[]->sum:)+(ch[]?ch[]->sum:)+dat)%md;
  31. sz=(ch[]?ch[]->sz:)+(ch[]?ch[]->sz:)+;
  32. }
  33. void pd()
  34. {
  35. if(rev)
  36. {
  37. swap(ch[],ch[]);
  38. if(ch[]) ch[]->rev^=;
  39. if(ch[]) ch[]->rev^=;
  40. rev=;
  41. }
  42. if(mulv!=)
  43. {
  44. if(ch[]) ch[]->pmul(mulv);
  45. if(ch[]) ch[]->pmul(mulv);
  46. mulv=;
  47. }
  48. if(addv)
  49. {
  50. if(ch[]) ch[]->padd(addv);
  51. if(ch[]) ch[]->padd(addv);
  52. addv=;
  53. }
  54. }
  55. }nodes[];
  56. LL mem;
  57. Node *getnode()
  58. {
  59. return nodes+(mem++);
  60. }
  61. bool isroot(Node *x)
  62. {
  63. return (!x->fa)||((x->fa->ch[]!=x)&&(x->fa->ch[]!=x));
  64. }
  65. bool gson(Node *o) {return o==o->fa->ch[];}//获得是父亲的左儿子(返回0)还是右儿子(1),要求保证存在父亲
  66. void rotate(Node *o,bool d)
  67. //在o子树中执行d=0左旋,d=1右旋,在旋转前不标记下传,并将o父节点的对应子节点由o变为需要值,要求保证存在子树(!d)
  68. {
  69. Node *k=o->ch[!d];if(!isroot(o)) o->fa->ch[gson(o)]=k;//注意这一句修改o父节点的要写在前面,曾经出过错调了一会
  70. o->ch[!d]=k->ch[d];k->ch[d]=o;
  71. o->upd();k->upd();
  72. k->fa=o->fa;o->fa=k;if(o->ch[!d]) o->ch[!d]->fa=o;
  73. }
  74. Node *st[];LL top;
  75. void solvetag(Node *o)
  76. {
  77. while(!isroot(o)) st[++top]=o,o=o->fa;
  78. st[++top]=o;
  79. while(top) st[top--]->pd();
  80. }
  81. void splay(Node *o)
  82. {
  83. solvetag(o);
  84. Node *fa,*fafa;bool d1,d2;
  85. while(!isroot(o))
  86. {
  87. fa=o->fa;d1=(o==fa->ch[]);
  88. if(isroot(fa)) rotate(fa,d1);
  89. else
  90. {
  91. fafa=o->fa->fa;d2=(fa==fafa->ch[]);//要保证fa不是root之后才能获取这两个值,曾错过
  92. if(d1==d2) rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去
  93. else rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去
  94. }
  95. }
  96. }
  97. void access(Node *o)
  98. {
  99. for(Node *lst=NULL;o;lst=o,o=o->fa)
  100. {
  101. splay(o);
  102. o->ch[]=lst;o->upd();
  103. }
  104. }
  105. Node *gtop(Node *o)
  106. {
  107. access(o);splay(o);
  108. for(;o->ch[];o=o->ch[],o->pd());
  109. splay(o);return o;
  110. }
  111. void mtop(Node *o) {access(o);splay(o);o->rev^=;}
  112. void split(Node *x,Node *y) {mtop(x);access(y);splay(y);}
  113. void link(Node *x,Node *y) {mtop(y);y->fa=x;}
  114. void cut(Node *x,Node *y) {split(x,y);x->fa=y->ch[]=NULL;y->upd();}
  115. LL query(Node *x,Node *y) {split(x,y);return y->sum;}
  116. void add(Node *x,Node *y,LL t) {split(x,y);y->padd(t);}
  117. void mul(Node *x,Node *y,LL t) {split(x,y);y->pmul(t);}
  118. }
  119. LCT::Node *nd[];
  120. LL n,q;char tmp[];
  121. int main()
  122. {
  123. LL i,x,y,t,x2,y2;
  124. scanf("%lld%lld",&n,&q);
  125. for(i=;i<=n;i++)
  126. {
  127. nd[i]=LCT::getnode();
  128. nd[i]->mulv=;nd[i]->dat=nd[i]->sum=;nd[i]->sz=;
  129. }
  130. for(i=;i<n;i++)
  131. {
  132. scanf("%lld%lld",&x,&y);
  133. LCT::link(nd[x],nd[y]);
  134. }
  135. while(q--)
  136. {
  137. scanf("%s",tmp);
  138. switch(tmp[])
  139. {
  140. case '+':
  141. scanf("%lld%lld%lld",&x,&y,&t);
  142. LCT::add(nd[x],nd[y],t);
  143. break;
  144. case '-':
  145. scanf("%lld%lld%lld%lld",&x,&y,&x2,&y2);
  146. LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
  147. break;
  148. case '*':
  149. scanf("%lld%lld%lld",&x,&y,&t);
  150. LCT::mul(nd[x],nd[y],t);
  151. break;
  152. case '/':
  153. scanf("%lld%lld",&x,&y);
  154. printf("%lld\n",LCT::query(nd[x],nd[y]));
  155. }
  156. }
  157. return ;
  158. }

重新打了一个板子

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cassert>
  4. #define md 51061
  5. using namespace std;
  6. typedef long long LL;
  7. int Add(int a,int b) {return (a+b)%md;}
  8. int Add(int a,int b,int c) {return (a+b+c)%md;}
  9. int Mul(int a,int b) {return LL(a)*b%md;}
  10. namespace LCT
  11. {
  12. const int N=;
  13. struct Node
  14. {
  15. Node *ch[],*fa;
  16. bool rev;
  17. int addv,mulv;
  18. int dat,sum,sz;
  19. void upd()
  20. {
  21. sum=Add((ch[]?ch[]->sum:),dat,(ch[]?ch[]->sum:));
  22. sz=(ch[]?ch[]->sz:)++(ch[]?ch[]->sz:);
  23. }
  24. void padd(int x) {addv=Add(addv,x);dat=Add(dat,x);sum=Add(sum,Mul(x,sz));}
  25. void pmul(int x) {addv=Mul(addv,x);mulv=Mul(mulv,x);dat=Mul(dat,x);sum=Mul(sum,x);}
  26. void pd()
  27. {
  28. if(rev)
  29. {
  30. swap(ch[],ch[]);
  31. if(ch[]) ch[]->rev^=;
  32. if(ch[]) ch[]->rev^=;
  33. rev=;
  34. }
  35. if(mulv!=)
  36. {
  37. if(ch[]) ch[]->pmul(mulv);
  38. if(ch[]) ch[]->pmul(mulv);
  39. mulv=;
  40. }
  41. if(addv)
  42. {
  43. if(ch[]) ch[]->padd(addv);
  44. if(ch[]) ch[]->padd(addv);
  45. addv=;
  46. }
  47. }
  48. bool isroot() {return (!fa)||(this!=fa->ch[]&&this!=fa->ch[]);}
  49. bool gson() {return this==fa->ch[];}
  50. void rot()//将自身向上旋,要求已经完成下传标记
  51. {
  52. bool d=gson();Node *f=fa;
  53. fa=f->fa;if(!f->isroot()) f->fa->ch[f->gson()]=this;
  54. f->ch[d]=ch[!d];if(ch[!d]) ch[!d]->fa=f;
  55. f->fa=this;ch[!d]=f;
  56. f->upd();upd();
  57. }
  58. }nodes[N+];
  59. Node *st[N+];int top;
  60. int mem;
  61. Node *getnode()
  62. {
  63. Node *t=nodes+mem++;t->mulv=;t->sz=;t->dat=t->sum=;
  64. return t;
  65. }
  66. void solvetag(Node *o)
  67. {
  68. while(!o->isroot()) st[++top]=o,o=o->fa;
  69. st[++top]=o;
  70. while(top) st[top--]->pd();
  71. }
  72. void splay(Node *o)
  73. {
  74. solvetag(o);
  75. for(;!o->isroot();o->rot())
  76. if(!o->fa->isroot())
  77. o->gson()==o->fa->gson()?o->fa->rot():o->rot();
  78. }
  79. void acc(Node *o)
  80. {
  81. for(Node *lst=;o;lst=o,o=o->fa)
  82. splay(o),o->ch[]=lst,o->upd();
  83. }
  84. void mtop(Node *o) {acc(o);splay(o);o->rev^=;}
  85. void link(Node *x,Node *y) {mtop(y);y->fa=x;}
  86. void cut(Node *x,Node *y) {mtop(x);acc(y);splay(y);x->fa=y->ch[]=;y->upd();}
  87. int query(Node *x,Node *y) {mtop(x);acc(y);splay(y);return y->sum;}
  88. void add(Node *x,Node *y,int t) {mtop(x);acc(y);splay(y);y->padd(t);}
  89. void mul(Node *x,Node *y,int t) {mtop(x);acc(y);splay(y);y->pmul(t);}
  90. }
  91. LCT::Node *nd[];
  92. int n,q;char tmp[];
  93. int main()
  94. {
  95. int i,x,y,t,x2,y2;
  96. scanf("%d%d",&n,&q);
  97. for(i=;i<=n;i++) nd[i]=LCT::getnode();
  98. for(i=;i<n;i++)
  99. {
  100. scanf("%d%d",&x,&y);
  101. LCT::link(nd[x],nd[y]);
  102. }
  103. while(q--)
  104. {
  105. scanf("%s",tmp);
  106. switch(tmp[])
  107. {
  108. case '+':
  109. scanf("%d%d%d",&x,&y,&t);
  110. LCT::add(nd[x],nd[y],t);
  111. break;
  112. case '-':
  113. scanf("%d%d%d%d",&x,&y,&x2,&y2);
  114. LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
  115. break;
  116. case '*':
  117. scanf("%d%d%d",&x,&y,&t);
  118. LCT::mul(nd[x],nd[y],t);
  119. break;
  120. case '/':
  121. scanf("%d%d",&x,&y);
  122. printf("%d\n",LCT::query(nd[x],nd[y]));
  123. }
  124. }
  125. return ;
  126. }

洛谷 P1501 [国家集训队]Tree II的更多相关文章

  1. 洛谷 P1501 [国家集训队]Tree II 解题报告

    P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...

  2. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  3. 【刷题】洛谷 P1501 [国家集训队]Tree II

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  4. 洛谷P1501 [国家集训队]Tree II(LCT)

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  5. 洛谷P1501 [国家集训队]Tree II(打标记lct)

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  6. [洛谷P1501][国家集训队]Tree II

    题目大意:给一棵树,有四种操作: $+\;u\;v\;c:$将路径$u->v$区间加$c$ $-\;u_1\;v_1\;u_2\;v_2:$将边$u_1-v_1$切断,改成边$u_2-v_2$, ...

  7. 洛谷 P1501 [国家集训队]Tree II Link-Cut-Tree

    Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...

  8. [洛谷P1501] [国家集训队]Tree II(LCT模板)

    传送门 这是一道LCT的板子题,说白了就是在LCT上支持线段树2的操作. 所以我只是来存一个板子,并不会讲什么(再说我也不会,只能误人子弟2333). 不过代码里的注释可以参考一下. Code #in ...

  9. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...

随机推荐

  1. Angular2.x-显示heroes列表

    在此页面中,您将展开Tour of Heroes应用程序以显示heroes列表,并允许用户选择heroes并显示heroes的详细信息. 6.X 你需要一些heroes来展示. 最终你会从远程数据服务 ...

  2. protobuf 一个c++示例

    http://wangjunle23.blog.163.com/blog/static/11783817120126155282640/     1.在.proto文件中定义消息格式 2.使用prot ...

  3. protobuf 之 MessageLite 接口摘录

    class LIBPROTOBUF_EXPORT MessageLite { public: inline MessageLite() {} virtual ~MessageLite(); // Ba ...

  4. POJ 1061 青蛙的约会(扩展GCD求模线性方程)

    题目地址:POJ 1061 扩展GCD好难懂.. 看了半天.最终把证明什么的都看明确了. .推荐一篇博客吧(戳这里),讲的真心不错.. 直接上代码: #include <iostream> ...

  5. 1 TypeScript 简介与安装

    简介: TypeScript 是一种由微软开发维护的自由和开源的编程语言,它是JavaScript的一个超集,支持可选的类型检查,扩展了JavaScript的语法,支持JavaScript的所有语法和 ...

  6. Navicat for MySQL出现1030-Got error 28 from storage engine错误

    Navicat for MySQL出现1030-Got error 28 from storage engine错误  刚刚还能用这会儿就用不了了,估计是磁盘空间不足引起的! 在根目录/下执行命令:d ...

  7. 2016/3/27 PHP中include和require的区别详解

    1.概要 require()语句的性能与include()相类似,都是包括并运行指定文件.不同之处在于:对include()语句来说,在执行文件时每次都要进行读取和评估:而对于require()来说, ...

  8. Tomcat最多支持并发多少用户?

    当一个进程有 500 个线程在跑的话,那性能已经是很低很低了.Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当然了,也可以将其改大.当某个应用拥有 250 个以上并发 ...

  9. MkDocs -- Project documentation with Markdown

    /************************************************************************ * MkDocs -- Project docume ...

  10. 《JAVA与模式》之调停者模式

    调停者模式是对象的行为模式.调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显引用.从而使它们可以较松散地耦合.当这些对象中的某些对象之间的相互作用发生改变时,不会立即影响到其他的一些 ...