题目链接 GSS

$GSS1$

对于每个询问$l$, $r$,查询$a_{l}$, $a_{l+1}$, $a_{l+2}$, ..., $a_{r}$这个序列的最大字段和。

建立线段树,每个节点维护四个信息

$c$:当前区间的元素和

$lc$:当前区间左端点开始的最大子序列和

$rc$:当前区间右端点结束的最大子序列和

$ret$:当前区间的答案

于是我们建立线段树的时候预处理出每个节点的四个信息,查询的时候返回一个节点,这个节点的$ret$即为答案。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define lson i << 1, L, mid
  8. #define rson i << 1 | 1, mid + 1, R
  9. #define ls i << 1
  10. #define rs i << 1 | 1
  11.  
  12. typedef long long LL;
  13.  
  14. const int N = 1e5 + 10;
  15.  
  16. struct node{
  17. int c, lc, rc, ret;
  18. } t[N << 2];
  19.  
  20. int n, q, l, r;
  21.  
  22. void pushup(int i){
  23. t[i].c = t[ls].c + t[rs].c;
  24. t[i].lc = max(t[ls].lc, t[ls].c + t[rs].lc);
  25. t[i].rc = max(t[rs].rc, t[rs].c + t[ls].rc);
  26. t[i].ret = max(max(t[ls].ret, t[rs].ret), t[ls].rc + t[rs].lc);
  27. }
  28.  
  29. void build(int i, int L, int R){
  30. if (L == R){
  31. scanf("%d", &t[i].ret);
  32. t[i].c = t[i].lc = t[i].rc = t[i].ret;
  33. return;
  34. }
  35.  
  36. int mid = (L + R) >> 1;
  37.  
  38. build(lson);
  39. build(rson);
  40. pushup(i);
  41. }
  42.  
  43. node query(int i, int L, int R, int l, int r){
  44. if (l == L && R == r) return t[i];
  45.  
  46. int mid = (L + R) >> 1;
  47.  
  48. if (r <= mid) return query(lson, l, r);
  49. if (l > mid) return query(rson, l, r);
  50.  
  51. node ta = query(lson, l, mid);
  52. node tb = query(rson, mid + 1, r);
  53.  
  54. node ans;
  55. ans.c = ta.c + tb.c;
  56. ans.lc = max(ta.lc, ta.c + tb.lc);
  57. ans.rc = max(tb.rc, tb.c + ta.rc);
  58. ans.ret = max(max(ta.ret, tb.ret), ta.rc + tb.lc);
  59. return ans;
  60. }
  61.  
  62. int main(){
  63.  
  64. while (~scanf("%d", &n)){
  65. build(1, 1, n);
  66. scanf("%d", &q);
  67. while (q--){
  68. scanf("%d%d", &l, &r);
  69. node ans = query(1, 1, n, l, r);
  70. printf("%d\n", ans.ret);
  71. }
  72. }
  73.  
  74. return 0;
  75. }

$GSS2$

$GSS1$的去重版

什么意思呢

询问的形式还是完全一样的,就是子序列的价值稍微变了一下。

$GSS1$中子序列的价值是该子序列的元素和,$GSS2$这里是该子序列出现过的元素的和

做法和$GSS1$完全不一样。

我们对询问离线。然后排序,按照右端点升序。

然后从左往右扫过去,每次加入$a_{i}$的时候, 先把$a_{i}$加进去。

接着我们对$last[a_{i}] + 1$到$i-1$这段区间都加上$a_{i}$,$last[x]$表示$x$上一次出现的位置,初值为$0$。

维护线段树的话我们需要四个信息。

$now$:当前这个时候区间的最大值

$mx$:历史区间的最大值

$h$:历史lazy标记(传给后代)的最大值

$add$:当前lazy标记(需传给后代)的值

然后查询一遍就可以了。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define lson i << 1, L, mid
  8. #define rson i << 1 | 1, mid + 1, R
  9. #define ls i << 1
  10. #define rs i << 1 | 1
  11. #define MP make_pair
  12. #define fi first
  13. #define se second
  14.  
  15. typedef long long LL;
  16.  
  17. const int N = 1e5 + 10;
  18. const int d = 1e5;
  19.  
  20. int n, m, x, y;
  21. int a[N], c[N << 1];
  22. vector <pair <int, int> > v[N];
  23. LL mx[N << 2], now[N << 2], add[N << 2], h[N << 2];
  24. LL ans[N];
  25.  
  26. void pushup(int i){
  27. mx[i] = max(mx[ls], mx[rs]);
  28. now[i] = max(now[ls], now[rs]);
  29. }
  30.  
  31. void pushdown(int i){
  32. h[ls] = max(h[ls], add[ls] + h[i]);
  33. h[rs] = max(h[rs], add[rs] + h[i]);
  34.  
  35. add[ls] += add[i];
  36. add[rs] += add[i];
  37.  
  38. mx[ls] = max(mx[ls], now[ls] + h[i]);
  39. mx[rs] = max(mx[rs], now[rs] + h[i]);
  40.  
  41. now[ls] += add[i];
  42. now[rs] += add[i];
  43.  
  44. add[i] = 0;
  45. h[i] = -1e16;
  46. }
  47.  
  48. void update(int i, int L, int R, int x, int val){
  49. if (L == R && L == x){
  50. mx[i] = now[i] = val;
  51. return;
  52. }
  53.  
  54. int mid = (L + R) >> 1;
  55. pushdown(i);
  56. if (x <= mid) update(lson, x, val);
  57. else update(rson, x, val);
  58. pushup(i);
  59. }
  60.  
  61. void Add(int i, int L, int R, int l, int r, int val){
  62. if (l <= L && R <= r){
  63. now[i] += val;
  64. mx[i] = max(mx[i], now[i]);
  65. add[i] += val;
  66. h[i] = max(h[i], add[i]);
  67. return ;
  68. }
  69.  
  70. int mid = (L + R) >> 1;
  71. pushdown(i);
  72. if (l <= mid) Add(lson, l, r, val);
  73. if (r > mid) Add(rson, l, r, val);
  74. pushup(i);
  75. }
  76.  
  77. LL query(int i, int L, int R, int l, int r){
  78. if (l <= L && R <= r) return mx[i];
  79. int mid = (L + R) >> 1;
  80. LL ret = -1e16;
  81. pushdown(i);
  82. if (l <= mid) ret = max(ret, query(lson, l, r));
  83. if (r > mid) ret = max(ret, query(rson, l, r));
  84. pushup(i);
  85. return ret;
  86. }
  87.  
  88. int main(){
  89.  
  90. scanf("%d", &n);
  91. rep(i, 1, n) scanf("%d", a + i);
  92. scanf("%d", &m);
  93.  
  94. rep(i, 1, ((n << 2) - 1)) mx[i] = h[i] = now[i] = -1e16;
  95.  
  96. rep(i, 1, m){
  97. scanf("%d%d", &x, &y);
  98. v[y].push_back(MP(x, i));
  99. }
  100.  
  101. rep(i, 1, n){
  102. update(1, 1, n, i, a[i]);
  103. if (c[a[i] + d] + 1 < i) Add(1, 1, n, c[a[i] + d] + 1, i - 1, a[i]);
  104. c[a[i] + d] = i;
  105. for (auto u : v[i]) ans[u.se] = query(1, 1, n, u.fi, i);
  106. }
  107.  
  108. rep(i, 1, m) printf("%lld\n", max(0ll, ans[i]));
  109. return 0;
  110. }

$GSS3$

$GSS1$加个单点更新,没了。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define lson i << 1, L, mid
  8. #define rson i << 1 | 1, mid + 1, R
  9. #define ls i << 1
  10. #define rs i << 1 | 1
  11.  
  12. typedef long long LL;
  13.  
  14. const int N = 1e5 + 10;
  15.  
  16. struct node{
  17. int c, lc, rc, ret;
  18. } t[N << 2];
  19.  
  20. int n, q, l, r;
  21. int op, x, y;
  22.  
  23. void pushup(int i){
  24. t[i].c = t[ls].c + t[rs].c;
  25. t[i].lc = max(t[ls].lc, t[ls].c + t[rs].lc);
  26. t[i].rc = max(t[rs].rc, t[rs].c + t[ls].rc);
  27. t[i].ret = max(max(t[ls].ret, t[rs].ret), t[ls].rc + t[rs].lc);
  28. }
  29.  
  30. void build(int i, int L, int R){
  31. if (L == R){
  32. scanf("%d", &t[i].ret);
  33. t[i].c = t[i].lc = t[i].rc = t[i].ret;
  34. return;
  35. }
  36.  
  37. int mid = (L + R) >> 1;
  38.  
  39. build(lson);
  40. build(rson);
  41. pushup(i);
  42. }
  43.  
  44. void update(int i, int L, int R, int x, int val){
  45. if (L == x && L == R){
  46. t[i].c = t[i].lc = t[i].rc = t[i].ret = val;
  47. return;
  48. }
  49.  
  50. int mid = (L + R) >> 1;
  51. if (x <= mid) update(lson, x, val);
  52. else update(rson, x, val);
  53. pushup(i);
  54. }
  55.  
  56. node query(int i, int L, int R, int l, int r){
  57. if (l == L && R == r) return t[i];
  58.  
  59. int mid = (L + R) >> 1;
  60.  
  61. if (r <= mid) return query(lson, l, r);
  62. if (l > mid) return query(rson, l, r);
  63.  
  64. node ta = query(lson, l, mid);
  65. node tb = query(rson, mid + 1, r);
  66.  
  67. node ans;
  68. ans.c = ta.c + tb.c;
  69. ans.lc = max(ta.lc, ta.c + tb.lc);
  70. ans.rc = max(tb.rc, tb.c + ta.rc);
  71. ans.ret = max(max(ta.ret, tb.ret), ta.rc + tb.lc);
  72. return ans;
  73. }
  74.  
  75. int main(){
  76.  
  77. scanf("%d", &n);
  78. build(1, 1, n);
  79. scanf("%d", &q);
  80. while (q--){
  81. scanf("%d", &op);
  82. if (op == 1){
  83. scanf("%d%d", &l, &r);
  84. node ans = query(1, 1, n, l, r);
  85. printf("%d\n", ans.ret);
  86. }
  87.  
  88. else{
  89. scanf("%d%d", &x, &y);
  90. update(1, 1, n, x, y);
  91. }
  92. }
  93.  
  94. return 0;
  95. }

$GSS4$

这题做法很暴力

对那些值已经全部是1的区间结点打上永久标记即可。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define ls i << 1
  8. #define rs i << 1 | 1
  9. #define lson ls, L, mid
  10. #define rson rs, mid + 1, R
  11.  
  12. typedef long long LL;
  13.  
  14. const int N = 1e5 + 10;
  15.  
  16. LL s[N << 2];
  17. int t[N << 2];
  18. int n;
  19. int q;
  20. int ca = 0;
  21.  
  22. inline void pushup(int i){
  23. s[i] = s[ls] + s[rs];
  24. t[i] = t[ls] & t[rs];
  25. }
  26.  
  27. void build(int i, int L, int R){
  28. if (L == R){
  29. scanf("%lld", s + i);
  30. t[i] = s[i] <= 1;
  31. return;
  32. }
  33.  
  34. int mid = (L + R) >> 1;
  35.  
  36. build(lson);
  37. build(rson);
  38. pushup(i);
  39. }
  40.  
  41. void update(int i, int L, int R, int l, int r){
  42. if (t[i]) return;
  43. if (L == R){
  44. s[i] = sqrt(s[i]);
  45. t[i] = s[i] <= 1;
  46. return;
  47. }
  48.  
  49. int mid = (L + R) >> 1;
  50. if (l <= mid) update(lson, l, r);
  51. if (r > mid) update(rson, l, r);
  52. pushup(i);
  53. }
  54.  
  55. LL query(int i, int L, int R, int l, int r){
  56. if (l <= L && R <= r) return s[i];
  57. int mid = (L + R) >> 1;
  58. LL ret = 0;
  59. if (l <= mid) ret += query(lson, l, r);
  60. if (r > mid) ret += query(rson, l, r);
  61. return ret;
  62. }
  63.  
  64. int main(){
  65.  
  66. while (~scanf("%d", &n)){
  67. printf("Case #%d:\n", ++ca);
  68. build(1, 1, n);
  69. scanf("%d", &q);
  70. while (q--){
  71. int op, x, y;
  72. scanf("%d%d%d", &op, &x, &y);
  73. if (x > y) swap(x, y);
  74. if (op == 1) printf("%lld\n", query(1, 1, n, x, y));
  75. else update(1, 1, n, x, y);
  76. }
  77. putchar(10);
  78. }
  79. return 0;
  80. }

  

$GSS5$

分类讨论,注意细节就可以了。

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. #define rep(i, a, b) for (int i(a); i <= (b); ++i)
  6. #define dec(i, a, b) for (int i(a); i >= (b); --i)
  7. #define lson i << 1, L, mid
  8. #define rson i << 1 | 1, mid + 1, R
  9. #define ls i << 1
  10. #define rs i << 1 | 1
  11.  
  12. const int N = 1e5 + 10;
  13.  
  14. struct node{
  15. int c, lc, rc, ret;
  16. } t[N << 2];
  17.  
  18. int T;
  19. int n, q, l, r;
  20. int a[N], s[N];
  21. int ans;
  22.  
  23. void pushup(int i){
  24. t[i].c = t[ls].c + t[rs].c;
  25. t[i].lc = max(t[ls].lc, t[ls].c + t[rs].lc);
  26. t[i].rc = max(t[rs].rc, t[rs].c + t[ls].rc);
  27. t[i].ret = max(max(t[ls].ret, t[rs].ret), t[ls].rc + t[rs].lc);
  28. }
  29.  
  30. void build(int i, int L, int R){
  31. if (L == R){
  32. t[i].ret = a[L];
  33. t[i].c = t[i].lc = t[i].rc = t[i].ret;
  34. return;
  35. }
  36.  
  37. int mid = (L + R) >> 1;
  38.  
  39. build(lson);
  40. build(rson);
  41. pushup(i);
  42. }
  43.  
  44. node query(int i, int L, int R, int l, int r){
  45. if (l == L && R == r) return t[i];
  46.  
  47. int mid = (L + R) >> 1;
  48.  
  49. if (r <= mid) return query(lson, l, r);
  50. if (l > mid) return query(rson, l, r);
  51.  
  52. node ta = query(lson, l, mid);
  53. node tb = query(rson, mid + 1, r);
  54.  
  55. node ans;
  56. ans.c = ta.c + tb.c;
  57. ans.lc = max(ta.lc, ta.c + tb.lc);
  58. ans.rc = max(tb.rc, tb.c + ta.rc);
  59. ans.ret = max(max(ta.ret, tb.ret), ta.rc + tb.lc);
  60. return ans;
  61. }
  62.  
  63. int main(){
  64.  
  65. scanf("%d", &T);
  66. while (T--){
  67. scanf("%d", &n);
  68. rep(i, 1, n) scanf("%d", a + i);
  69. rep(i, 1, n) s[i] = s[i - 1] + a[i];
  70. build(1, 1, n);
  71. scanf("%d", &q);
  72. while (q--){
  73. int x1, y1, x2, y2;
  74. scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
  75. ans = 0;
  76. if (x2 == y1){
  77. ans = query(1, 1, n, x1, y1).rc + query(1, 1, n, x2, y2).lc - a[y1];
  78. printf("%d\n", ans);
  79. }
  80.  
  81. else if (y1 < x2){
  82. ans = s[x2 - 1] - s[y1];
  83. ans += query(1, 1, n, x1, y1).rc + query(1, 1, n, x2, y2).lc;
  84. printf("%d\n", ans);
  85. }
  86.  
  87. else{
  88. ans = query(1, 1, n, x2, y1).ret;
  89. ans = max(ans, s[y1 - 1] - s[x2] + query(1, 1, n, x1, x2).rc + query(1, 1, n, y1, y2).lc);
  90. ans = max(ans, query(1, 1, n, x1, x2).rc + query(1, 1, n, x2, y1).lc - a[x2]);
  91. ans = max(ans, query(1, 1, n, x2, y1).rc + query(1, 1, n, y1, y2).lc - a[y1]);
  92. printf("%d\n", ans);
  93. }
  94. }
  95.  
  96. }
  97.  
  98. return 0;
  99. }

  

SPOJ GSS系列(数据结构维护技巧入门)的更多相关文章

  1. 【SPOJ GSS】数据结构题选做

    SPOJ GSS1 题意:给一个序列以及一些询问,每个是问\([l,r]\)中最大连续子序列和是多少. 思路:这个问题是以下问题的基础. 我们考虑用线段树来解决这个问题. 首先我们来想想如果要求出最大 ...

  2. SPOJ GSS 系列

    来怒做GSS系列了: GSS1:https://www.luogu.org/problemnew/show/SP1043 这题就是维护一个 sum , mx , lmx , rmx,转移时用结构体就好 ...

  3. spoj GSS系列简要题解

    文章目录 GSS1 GSS2 GSS3 GSS4 GSS5 GSS6 GSS7 GSS8 传送门 这个GSSGSSGSS系列全部是跟子段有关的数据结构菜题. 于是来水一篇博客. GSS1 传送门 题意 ...

  4. SPOJ GSS系列

    众所周知的仅次于ynoi的毒瘤数据结构系列.(跟Qtree系列并列?) GSS1: 长度为 $n$ 的序列 $a$,$m$ 个询问,每次询问区间 $[l,r]$ 之间的最大子段和. $1\le n,m ...

  5. 数据结构与算法入门系列教程-C#

    数据结构与算法入门系列教程 (一)为啥要学习数据结构与算法 曾经我也以为自己很牛逼,工作中同事也觉得我还可以,领导也看得起我,啥啥啥都好,就这样过了几年,忽然发现自己学新东西没劲.时代都变了,而我还只 ...

  6. 一起学微软Power BI系列-官方文档-入门指南(3)Power BI建模

    我们前2篇文章:一起学微软Power BI系列-官方文档-入门指南(1)Power BI初步介绍 和一起学微软Power BI系列-官方文档-入门指南(2)获取源数据 中,我们介绍了官方入门文档与获取 ...

  7. 一起学微软Power BI系列-官方文档-入门指南(4)Power BI的可视化

    在前面的系列文章中,我们介绍了官方有关获取数据,以及建模的原始文档和基本介绍.今天继续给大家介绍官方文档中,有关可视化的内容.实际上获获取数据和建模更注重业务关系的处理,而可视化则关注对数据的解读.这 ...

  8. 一起学微软Power BI系列-官方文档-入门指南(5)探索数据奥秘

    我们几篇系列文章中,我们介绍了官方入门文档与获取数据等基本知识.今天继续给大家另外一个重点,探索数据奥秘.有了数据源,有了模型,下一步就是如何解析数据了.解析数据的过程需要很多综合技能,不仅仅是需要掌 ...

  9. ShoneSharp语言(S#)的设计和使用介绍系列(4)— 入门概述

    ShoneSharp语言(S#)的设计和使用介绍 系列(4)- 入门概述 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...

随机推荐

  1. jCarousel,jQuery下的滚动切换传送插件

    转自:http://www.zhangxinxu.com/jq/jcarousel_zh/#Examples 介绍 jCarousel是一款 jQuery 插件, 用来控制水平或垂直排列的列表项. 这 ...

  2. Linux安装配置***客户端

    1.创建root用户 sudo passwd root su root 2.安装shadowsocks sudo apt-get install python-pip sudo pip install ...

  3. for_each_node(node)

    遍历各个pg_data_t节点. 1.定义在include/linux/nodemask.h中 /* * Bitmasks that are kept for all the nodes. */ en ...

  4. 数学基础:HUD1406-完数

    完数 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Descript ...

  5. c++,友元类和友元函数

    都是声明时友元的东西可以访问自己类的私有和保护成员 类的友元 友元是C++提供的一种破坏数据封装和数据隐藏的机制. 通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息 ...

  6. 在终端更改MAC的MySQL的root密码

  7. CodeForces Round #320 Div2

    A. Raising Bacteria 计算一下x的bitcount就是答案. #include <iostream> #include <cstdio> #include & ...

  8. UVa 1354 枚举子集 Mobile Computing

    只要枚举左右两个子天平砝码的集合,我们就能算出左右两个悬挂点到根悬挂点的距离. 但是题中要求找尽量宽的天平但是不能超过房间的宽度,想不到要怎样记录结果. 参考别人代码,用了一个结构体的vector,保 ...

  9. [POJ 1006] Biorhythms C++解题

        Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 107569   Accepted: 33365 ...

  10. ogre3D学习基础9 -- 光源程序实例

    这一章练习一下光源的使用,光源分为三种:点光源,聚光源,有向光.具体内容前面说过,这里就不解释了. 继续在上一章的程序的基础上实现. 1.创建摄像机(Camera) createCamera()函数是 ...