题面

Sample Input

  1. 5 7
  2. 2 -1 -3 1 1
  3. 1 2
  4. 1 3
  5. 3 4
  6. 3 5
  7. 2
  8. 1 3 0
  9. 2
  10. 1 2 1
  11. 2
  12. 1 1 -3
  13. 2

Sample Output

  1. 2
  2. 4
  3. 5
  4. 2

HINT

Solution

首先考虑序列上的这个问题: 给定一个序列, 有两种操作

  • 修改一个位置上的值
  • 询问某个区间中的连续段的最大权值和

做法是: 用一个线段树维护这个序列, 每个节点所对应的区间记录以下4个信息:

  • sum表示整个区间的权值和
  • leftMax表示以包含从最左边开始的区间的连续段最大权值和
  • rightMax与上面相反
  • max表示整个区间中连续段最大权值和

则我们可以通过上述信息合并两个区间的信息.

考虑如何转化到树上解决: 我们首先进行树链剖分. 我们用sum[u]记录\(u\)这个点的权值加上以\(u\)的每个字节点为根的连通块的最大权值和. 我们用类似于序列上的方法维护\(sum\)即可. 修改一个点的权值时, 往上跳修改即可.

实现的时候把线段树上的信息合并重载为运算符会比较简洁.

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <set>
  6. using namespace std;
  7. namespace Zeonfai
  8. {
  9. inline int getInt()
  10. {
  11. int a = 0, sgn = 1; char c;
  12. while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
  13. while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
  14. return a * sgn;
  15. }
  16. }
  17. const int N = (int)1e5;
  18. int n;
  19. multiset<int> ans;
  20. struct data
  21. {
  22. int leftMax, rightMax, mx, sum;
  23. inline data() { leftMax = rightMax = mx = sum = 0; }
  24. inline data friend operator +(const data &a, const data &b)
  25. {
  26. data res;
  27. res.sum = a.sum + b.sum;
  28. res.leftMax = max(a.leftMax, a.sum + b.leftMax);
  29. res.rightMax = max(b.rightMax, b.sum + a.rightMax);
  30. res.mx = max(res.leftMax, res.rightMax);
  31. res.mx = max(res.mx, a.mx); res.mx = max(res.mx, b.mx);
  32. res.mx = max(res.mx, a.rightMax + b.leftMax);
  33. return res;
  34. }
  35. };
  36. struct segmentTree
  37. {
  38. data nd[N << 2];
  39. void modify(int u, int L, int R, int pos, int x)
  40. {
  41. if (L == R)
  42. {
  43. nd[u].leftMax = nd[u].rightMax = nd[u].mx = max(0, x);
  44. nd[u].sum = x;
  45. return;
  46. }
  47. if (pos <= L + R >> 1) modify(u << 1, L, L + R >> 1, pos, x);
  48. else modify(u << 1 | 1, (L + R >> 1) + 1, R, pos, x);
  49. nd[u] = nd[u << 1] + nd[u << 1 | 1];
  50. }
  51. inline void modify(int pos, int x) { modify(1, 1, n, pos, x); }
  52. data query(int u, int curL, int curR, int L, int R)
  53. {
  54. if (curL >= L && curR <= R) return nd[u];
  55. int mid = curL + curR >> 1;
  56. data res;
  57. if (L <= mid) res = res + query(u << 1, curL, mid, L, R);
  58. if (R > mid) res = res + query(u << 1 | 1, mid + 1, curR, L, R);
  59. return res;
  60. }
  61. inline data query(int L, int R) { return query(1, 1, n, L, R); }
  62. }seg;
  63. struct tree
  64. {
  65. struct node
  66. {
  67. int w;
  68. vector<int> edg; int pre;
  69. int sz, hvy;
  70. int tp, id, lst;
  71. int sum;
  72. inline node() { edg.clear(); }
  73. }nd[N + 1];
  74. inline void addEdge(int u, int v) { nd[u].edg.push_back(v); nd[v].edg.push_back(u); }
  75. void getSize(int u, int pre)
  76. {
  77. nd[u].pre = pre; nd[u].hvy = -1; nd[u].sz = 1;
  78. for (auto v : nd[u].edg) if (v != pre)
  79. {
  80. getSize(v, u); nd[u].sz += nd[v].sz;
  81. if (nd[u].hvy == -1 || nd[v].sz > nd[nd[u].hvy].sz) nd[u].hvy = v;
  82. }
  83. }
  84. int clk;
  85. int work(int u, int tp)
  86. {
  87. nd[u].tp = tp; nd[u].id = ++ clk;
  88. if (~ nd[u].hvy) work(nd[u].hvy, tp);
  89. else
  90. {
  91. for (int v = u; v != nd[u].tp; v = nd[v].pre) nd[v].lst = nd[u].id;
  92. nd[nd[u].tp].lst = nd[u].id;
  93. }
  94. nd[u].sum = nd[u].w;
  95. for (auto v : nd[u].edg) if (v != nd[u].pre && v != nd[u].hvy) nd[u].sum += work(v, v);
  96. seg.modify(nd[u].id, nd[u].sum);
  97. if (u == tp)
  98. {
  99. data res = seg.query(nd[u].id, nd[u].lst);
  100. ans.insert(res.mx);
  101. return res.leftMax;
  102. }
  103. return 0;
  104. }
  105. inline void decomposition() { getSize(1, -1); clk = 0; work(1, 1); }
  106. inline void modify(int u, int x)
  107. {
  108. int tmp = nd[u].w; nd[u].w = x;
  109. for (; ~ u; u = nd[nd[u].tp].pre)
  110. {
  111. nd[u].sum = nd[u].sum - tmp + x;
  112. data res = seg.query(nd[nd[u].tp].id, nd[nd[u].tp].lst);
  113. tmp = res.leftMax;
  114. ans.erase(ans.find(res.mx));
  115. seg.modify(nd[u].id, nd[u].sum);
  116. res = seg.query(nd[nd[u].tp].id, nd[nd[u].tp].lst);
  117. x = res.leftMax;
  118. ans.insert(res.mx);
  119. }
  120. }
  121. }T;
  122. int main()
  123. {
  124. #ifndef ONLINE_JUDGE
  125. freopen("sub.in", "r", stdin);
  126. freopen("sub.out", "w", stdout);
  127. #endif
  128. using namespace Zeonfai;
  129. n = getInt(); int m = getInt();
  130. for (int i = 1; i <= n; ++ i) T.nd[i].w = getInt();
  131. for (int i = 1, u, v; i < n; ++ i) u = getInt(), v = getInt(), T.addEdge(u, v);
  132. ans.clear();
  133. T.decomposition();
  134. for (int i = 0; i < m; ++ i)
  135. {
  136. int opt = getInt();
  137. if (opt == 1)
  138. {
  139. int u = getInt(), x = getInt();
  140. T.modify(u, x);
  141. }
  142. else
  143. {
  144. multiset<int>::iterator p = ans.end();
  145. printf("%d\n", *(-- p));
  146. }
  147. }
  148. }

NOI模拟题1 Problem A: sub的更多相关文章

  1. NOI模拟题6 Problem C: Circle

    Solution 首先这个矩阵, 很明显的就是Vandermonde矩阵. 我们有公式: \[ |F_n| = \prod_{1 \le j < i \le n} (a_i - a_j) \] ...

  2. NOI模拟题5 Problem A: 开场题

    Solution 注意到\(\gcd\)具有结合律: \[ \gcd(a, b, c) = \gcd(a, \gcd(b, c)) \] 因此我们从后往前, 对于每个位置\(L\), 找到每一段不同的 ...

  3. NOI模拟题4 Problem C: 填格子(board)

    Solution 首先我们要有敏锐的直觉: 我们将每一列中不选哪种颜色看作是一个序列, 则我们发现这个序列要求相邻两位的颜色不同. 我们还发现, 一个这样的序列对应两种不同的合法的棋盘, 因此统计合法 ...

  4. NOI模拟题4 Problem B: 小狐狸(fox)

    Solution 考虑分开统计朝向每一个方向的所有狐狸对答案的贡献. 比如说以向右为例, 我们用箭标表示每一只狐狸的方向, 用\('\)表示当前一步移动之前的每一只狐狸的位置. \[ \begin{a ...

  5. NOI模拟题4 Problem A: 生成树(mst)

    Solution 我们考虑答案的表达式: \[ ans = \sqrt{\frac{\sum_{i = 1}^{n - 1} (w_i - \overline{w})^2}{n - 1}} \] 其中 ...

  6. 花海漫步 NOI模拟题

    题目好像难以看懂? 题目大意 给出一个字符串\(S\),统计满足以下条件的\((i,j,p,q)\)的数量. \(i \leq j, p \leq q\) \(S[i..j],S[p..q]\)是回文 ...

  7. 神奇的矩阵 NOI模拟题

    神奇的矩阵 题目大意 有一个矩阵\(A\),第一行是给出的,接下来第\(x\)行,第\(y\)个元素的值为数字\(A_{x-1,y}\)在\(\{A_{x-1,1},A_{x-1,2},A_{x-1, ...

  8. Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem K. UTF-8 Decoder 模拟题

    Problem K. UTF-8 Decoder 题目连接: http://opentrains.snarknews.info/~ejudge/team.cgi?SID=c75360ed7f2c702 ...

  9. 2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem I. Interest Targeting 模拟题

    Problem I. Interest Targeting 题目连接: http://codeforces.com/gym/100714 Description A unique display ad ...

随机推荐

  1. CQRS之旅——旅程5(准备发布V1版本)

    旅程5:准备发布V1版本 添加功能和重构,为V1版本发布做准备. "大多数人在完成一件事之后,就像留声机的唱片一样,一遍又一遍地使用它,直到它破碎,忘记了过去是用来创造更多未来的东西.&qu ...

  2. SSRS 报表管理器 http://localhost/Reports HTTP500 内部错误处理过程

    原文地址:http://www.cnblogs.com/zzry/p/5716056.html 安装了很多机器的sqlserverBI 组件 初始安装配置下 浏览报表管理器 http://localh ...

  3. idea 占用内存优化调整

      idea 占用内存优化调整 https://www.cnblogs.com/metoy/p/5967696.html   https://blog.csdn.net/zdxxinlang/arti ...

  4. Struts之准备工作

    *Struts之需要准备的jar包: *Struts之xml配置文件: <?xml version="1.0" encoding="UTF-8"?> ...

  5. Windows网络编程笔记5 -- 其他套接字

    包括红外线套接字(IrSock).IPX/SPX 套接字.NetBIOS 套接字.AppleTalk 套接字.ATM 套接字等.对这些套接字进行简单介绍. 第一.红外线套接字(I r S o c k) ...

  6. Python 模块搜索路径

    Python 会在什么地方寻找文件来导入模块? 使用命名为 path 变量的存储在标准 sys 模块 下的一系列目录名和 ZIP 压缩文件. 你可以读取和修改这个列表.下面是在我的 Mac 上 Pyt ...

  7. 使用anaconda

    Please run $ source /opt/anaconda/bin/activate root    $ source /opt/anaconda/bin/deactivate root to ...

  8. 使用CORS解决flask前端页面跨域问题

    from flask import Flask from flask_cors import CORS app = Flask(__name__) CORS(app) @app.route(" ...

  9. jquery版右下角弹窗效果

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  10. 关于可图化序列的一点结论 NEU 1429

    Graphic Sequence A graphic sequence is a sequence of numbers which can be the degree sequence of som ...