嘟嘟嘟




这道题其实还是挺基础的,只不过操作有点多。




区间乘和区间加按线段树的方式想。

那么就先要下放乘标记,再下放加标记。但这两个和反转标记是没有先后顺序的。

对于区间加,sum加的是区间长度\(*\)lazy标记。但是线段树区间固定,而lct不是,所以还要单独维护一个size。

还有一点,这个是splay的性质,就是当前节点的sum还要算上自己的权值,而不像线段树完全由子树信息合并而来。

最最最后一点,得开long long,包括点权。

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cmath>
  4. #include<algorithm>
  5. #include<cstring>
  6. #include<cstdlib>
  7. #include<cctype>
  8. #include<vector>
  9. #include<stack>
  10. #include<queue>
  11. using namespace std;
  12. #define enter puts("")
  13. #define space putchar(' ')
  14. #define Mem(a, x) memset(a, x, sizeof(a))
  15. #define In inline
  16. typedef long long ll;
  17. typedef double db;
  18. const int INF = 0x3f3f3f3f;
  19. const db eps = 1e-8;
  20. const int maxn = 1e5 + 5;
  21. const ll mod = 51061;
  22. inline ll read()
  23. {
  24. ll ans = 0;
  25. char ch = getchar(), last = ' ';
  26. while(!isdigit(ch)) last = ch, ch = getchar();
  27. while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  28. if(last == '-') ans = -ans;
  29. return ans;
  30. }
  31. inline void write(ll x)
  32. {
  33. if(x < 0) x = -x, putchar('-');
  34. if(x >= 10) write(x / 10);
  35. putchar(x % 10 + '0');
  36. }
  37. int n, q;
  38. char c[2];
  39. struct Tree
  40. {
  41. int ch[2], fa;
  42. int siz, rev;
  43. ll val, sum, add, mul;
  44. }t[maxn];
  45. In void c_rev(int now)
  46. {
  47. swap(t[now].ch[0], t[now].ch[1]);
  48. t[now].rev ^= 1;
  49. }
  50. In void c_mul(int now, ll lzy)
  51. {
  52. t[now].sum *= lzy; t[now].sum %= mod;
  53. t[now].val *= lzy; t[now].val %= mod;
  54. t[now].mul *= lzy; t[now].mul %= mod;
  55. t[now].add *= lzy; t[now].add %= mod;
  56. }
  57. In void c_add(int now, ll lzy)
  58. {
  59. t[now].sum += lzy * (ll)t[now].siz; t[now].sum %= mod;
  60. t[now].val += lzy; t[now].val %= mod;
  61. t[now].add += lzy; t[now].add %= mod;
  62. }
  63. In void pushdown(int now)
  64. {
  65. if(t[now].rev)
  66. {
  67. if(t[now].ch[0]) c_rev(t[now].ch[0]);
  68. if(t[now].ch[1]) c_rev(t[now].ch[1]);
  69. t[now].rev = 0;
  70. }
  71. if(t[now].mul != 1)
  72. {
  73. if(t[now].ch[0]) c_mul(t[now].ch[0], t[now].mul);
  74. if(t[now].ch[1]) c_mul(t[now].ch[1], t[now].mul);
  75. t[now].mul = 1;
  76. }
  77. if(t[now].add)
  78. {
  79. if(t[now].ch[0]) c_add(t[now].ch[0], t[now].add);
  80. if(t[now].ch[1]) c_add(t[now].ch[1], t[now].add);
  81. t[now].add = 0;
  82. }
  83. }
  84. In void pushup(int now)
  85. {
  86. t[now].siz = t[t[now].ch[0]].siz + t[t[now].ch[1]].siz + 1;
  87. t[now].sum = (t[t[now].ch[0]].sum + t[t[now].ch[1]].sum + t[now].val) % mod;
  88. }
  89. In bool n_root(int now)
  90. {
  91. return t[t[now].fa].ch[0] == now || t[t[now].fa].ch[1] == now;
  92. }
  93. In void rotate(int x)
  94. {
  95. int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x);
  96. if(n_root(y)) t[z].ch[t[z].ch[1] == y] = x; t[x].fa = z;
  97. t[y].ch[k] = t[x].ch[k ^ 1]; t[t[y].ch[k]].fa = y;
  98. t[x].ch[k ^ 1] = y; t[y].fa = x;
  99. pushup(y), pushup(x);
  100. }
  101. int st[maxn], top = 0;
  102. In void splay(int x)
  103. {
  104. int y = x;
  105. st[top = 1] = y;
  106. while(n_root(y)) st[++top] = y = t[y].fa;
  107. while(top) pushdown(st[top--]);
  108. while(n_root(x))
  109. {
  110. int y = t[x].fa, z = t[y].fa;
  111. if(n_root(y)) rotate(((t[y].ch[0] == x) ^ (t[z].ch[0] == y)) ? x : y);
  112. rotate(x);
  113. }
  114. }
  115. In void access(int x)
  116. {
  117. int y = 0;
  118. while(x)
  119. {
  120. splay(x); t[x].ch[1] = y;
  121. pushup(x);
  122. y = x; x = t[x].fa;
  123. }
  124. }
  125. In void make_root(int x)
  126. {
  127. access(x); splay(x);
  128. c_rev(x);
  129. }
  130. In int find_root(int x)
  131. {
  132. access(x); splay(x);
  133. while(t[x].ch[0]) pushdown(x), x = t[x].ch[0];
  134. return x;
  135. }
  136. In void split(int x, int y)
  137. {
  138. make_root(x);
  139. access(y); splay(y);
  140. }
  141. In void Link(int x, int y)
  142. {
  143. make_root(x);
  144. if(find_root(y) != x) t[x].fa = y;
  145. }
  146. In void Cut(int x, int y)
  147. {
  148. make_root(x);
  149. if(find_root(y) == x && t[x].fa == y && !t[x].ch[1])
  150. t[y].ch[0] = t[x].fa = 0, pushup(y);
  151. }
  152. int main()
  153. {
  154. n = read(); q = read();
  155. for(int i = 1; i <= n; ++i) t[i].val = t[i].mul = t[i].siz = 1;
  156. for(int i = 1, x, y; i < n; ++i) x = read(), y = read(), Link(x, y);
  157. for(int i = 1; i <= q; ++i)
  158. {
  159. scanf("%s", c); int x = read(), y = read();
  160. if(c[0] == '+') {int d = read(); split(x, y); c_add(y, d);}
  161. else if(c[0] == '*') {int d = read(); split(x, y); c_mul(y, d);}
  162. else if(c[0] == '/') split(x, y), write(t[y].sum), enter;
  163. else
  164. {
  165. Cut(x, y);
  166. x = read(), y = read();
  167. Link(x, y);
  168. }
  169. }
  170. return 0;
  171. }

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

  1. P1501 [国家集训队]Tree II(LCT)

    P1501 [国家集训队]Tree II 看着维护吧2333333 操作和维护区间加.乘线段树挺像的 进行修改操作时不要忘记吧每个点的点权$v[i]$也处理掉 还有就是$51061^2=2607225 ...

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

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

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

    题目链接 Tree Ⅱ\(=\)[模板]LCT+[模板]线段树2.. 分别维护3个标记,乘的时候要把加法标记也乘上. 还有就是模数的平方刚好爆\(int\),所以开昂赛德\(int\)就可以了. 我把 ...

  4. 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)

    点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...

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

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

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

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

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

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

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

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

  9. p1501 [国家集训队]Tree II

    传送门 分析 lct板子题 单独维护一下加和乘的情况即可 维护方法和维护翻转差不多 代码 #include<iostream> #include<cstdio> #includ ...

随机推荐

  1. 【C#设计模式-抽象工厂模式】

    一.抽象工厂模式的定义: 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 二.抽象工厂模式的结构: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模 ...

  2. bind(port)与.localAddress(new InetSocketAddress(port))区别

    两者并没有什么区别,最后都会调用AbstractBootstrap这个抽象类的bind()方法.

  3. HDU1698(KB7-E 线段树)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. CSS画0.5px的线

    今天遇到一个需求,画0.5px的线,查了以下资料,主要以scale方法为主.代码如下: /*0.5px上边框*/ .half_top_border_before:before{ content: &q ...

  5. 【读书笔记】iOS-网络-同步请求,队列式异步请求,异步请求的区别

    一,同步请求的最佳实践. 1,只在后台过程中使用同步请求,除非确定访问的是本地文件资源,否则请不要在主线程上使用. 2,只有在知道返回的数据不会超出应用的内存时才使用同步请求.记住,整个响应体都会位于 ...

  6. php将多个值的数组去除重复元素

    array_unique(array) 只能处理value只有单个的数组. 去除有多个value数组,可以使用如下函数实现: function more_array_unique($arr=array ...

  7. CSS 美化复选框 - 无图片方式

    今天和大家分享一个不使用图片美化复选框的方式.来看下效果图吧,如下是3种不同状态下的效果: 一. Html结构 <div class="check-wrap"> < ...

  8. 搭建ReactNative时的最普遍的错误—— ":CFBundleIdentifier", Does Not Exist

    报错 ":CFBundleIdentifier", Does Not Exist 今天搭建Reactnative 报错 注意当你第一次搭建RN时,包体下载的都是最新的版本,由于现在 ...

  9. 关于TCP/IOCP构架中出现的假死连接解决方案

    如果在2台不同的公网机器,对TCP的c/s做过详细的压力测试,那么很不幸,会有很多人发现自己的server端会出现大量的假死连接. 假死连接具体表现如下: 1.在s端机器上,会有一些处于TCP_EST ...

  10. Linux —— Vi 命令介绍

    简介 vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器. 这里只是简单地介绍一下它的用法和一小部分指令. 由于对Unix及Linux系统的任何版本,vi编辑 ...