求一个区间的最大连续子序列,基本想法就是分治,这段子序列可能在区间的左半边,也可能在区间的右半边,也有可能是横跨区间中点,这样就是左子区间的最大后缀加上右子区间的最大前缀之和。

线段树维护三个信息:区间最大前缀、最大后缀、最大连续子区间的下标。

最大前缀可以通过递推来求:要么是左子区间的最大前缀和、要么是左子区间的和 加上 右子区间的最大前缀和

最大后缀和的递推类似。

递推之前要预处理整个序列的前缀和。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #define MP make_pair
  5 #define lch(o) (o*2)
  6 #define rch(o) (o*2+1)
  7 using namespace std;
  8
  9 typedef long long LL;
 10 typedef pair<int, int> Interval;
 11 const int maxn = 500000 + 10;
 12 const int maxnode = 1000000 + 10;
 13
 14 LL prefix_sum[maxn];
 15
 16 LL sum(int a, int b) { return prefix_sum[b] - prefix_sum[a-1]; }
 17
 18 LL sum(Interval p) { return sum(p.first, p.second); }
 19
 20 Interval better(Interval a, Interval b)
 21 {
 22     if(sum(a) != sum(b)) return sum(a) > sum(b) ? a : b;
 23     return a < b ? a : b;    //pair自带字典序
 24 }
 25
 26 int qL, qR; //查询区间
 27
 28 struct IntervalTree
 29 {
 30     int max_prefix[maxnode], max_suffix[maxnode];
 31     Interval max_sub[maxnode];
 32
 33     void build(int o, int L, int R)
 34     {
 35         if(L == R) { max_prefix[o] = max_suffix[o] = L; max_sub[o] = MP(L, L); }
 36         else
 37         {
 38             int M = (L + R) >> 1;
 39             int lc = lch(o), rc = rch(o);
 40             build(lc, L, M);
 41             build(rc, M+1, R);
 42
 43             //递推max_prefix
 44             LL v1 = sum(L, max_prefix[lc]);
 45             LL v2 = sum(L, max_prefix[rc]);
 46             if(v1 == v2) max_prefix[o] = min(max_prefix[lc], max_prefix[rc]);
 47             else max_prefix[o] = v1 > v2 ? max_prefix[lc] : max_prefix[rc];
 48
 49             //递推max_suffix
 50             v1 = sum(max_suffix[lc], R);
 51             v2 = sum(max_suffix[rc], R);
 52             if(v1 == v2) max_suffix[o] = min(max_suffix[lc], max_suffix[rc]);
 53             else max_suffix[o] = v1 > v2 ? max_suffix[lc] : max_suffix[rc];
 54
 55             //递推max_sub
 56             max_sub[o] = better(max_sub[lc], max_sub[rc]);
 57             max_sub[o] = better(max_sub[o], MP(max_suffix[lc], max_prefix[rc]));
 58         }
 59     }
 60
 61     Interval query_prefix(int o, int L, int R)
 62     {
 63         if(max_prefix[o] <= qR) return MP(L, max_prefix[o]);
 64         int M = (L + R) >> 1;
 65         int lc = lch(o), rc = rch(o);
 66         if(qR <= M) return query_prefix(lc, L, M);
 67         Interval i = query_prefix(rc, M+1, R);
 68         i.first = L;
 69         return better(i, MP(L, max_prefix[lc]));
 70     }
 71
 72     Interval query_suffix(int o, int L, int R)
 73     {
 74         if(max_suffix[o] >= qL) return MP(max_suffix[o], R);
 75         int M = (L + R) >> 1;
 76         int lc = lch(o), rc = rch(o);
 77         if(qL > M) return query_suffix(rc, M+1, R);
 78         Interval i = query_suffix(lc, L, M);
 79         i.second = R;
 80         return better(i, MP(max_suffix[rc], R));
 81     }
 82
 83     Interval query(int o, int L, int R)
 84     {
 85         if(qL <= L && R <= qR) return max_sub[o];
 86         int M = (L + R) >> 1;
 87         int lc = lch(o), rc = rch(o);
 88         if(qR <= M) return query(lc, L, M);
 89         if(qL > M) return query(rc, M+1, R);
 90         Interval i1 = query_suffix(lc, L, M);//左子区间的最大后缀
 91         Interval i2 = query_prefix(rc, M+1, R);//右子区间的最大前缀
 92         Interval i3 = better(query(lc, L, M), query(rc, M+1, R));//两个子区间的最大连续和
 93         return better(i3, MP(i1.first, i2.second));
 94     }
 95 }tree;
 96
 97 int main()
 98 {
 99     //freopen("in.txt", "r", stdin);
100
101     int kase = 0, n, a, Q;
102     while(scanf("%d%d", &n, &Q) == 2)
103     {
104         prefix_sum[0] = 0;
105         for(int i = 1; i <= n; i++) { scanf("%d", &a); prefix_sum[i] = prefix_sum[i-1] + a; }
106         tree.build(1, 1, n);
107         printf("Case %d:\n", ++kase);
108         while(Q--)
109         {
110             int L, R;
111             scanf("%d%d", &L, &R);
112             qL = L; qR = R;
113             Interval ans = tree.query(1, 1, n);
114             printf("%d %d\n", ans.first, ans.second);
115         }
116     }
117
118     return 0;
119 }

代码君

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4356495.html

UVa 1400 (线段树) Ray, Pass me the dishes!相关推荐

  1. 线段树(区间合并) LA 3989 Ray, Pass me the dishes!

    题目传送门 题意:动态最大连续子序列和,静态的题目 分析:nlogn的归并思想.线段树维护结点的三个信息,最大前缀和,最大后缀和,该区间的最大和的两个端点,然后答案是三个的better.书上用pair ...

  2. UVA - 11992 线段树

    UVA - 11992 题意:有一个 r*c 的全 0矩阵, 进行 3 种操作. 1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中 ...

  3. UVa 11992 (线段树 区间修改) Fast Matrix Operations

    比较综合的一道题目. 二维的线段树,支持区间的add和set操作,然后询问子矩阵的sum,min,max 写完这道题也是醉醉哒,代码仓库里还有一份代码就是在query的过程中也pushdown向下传递 ...

  4. uva 12086 线段树or树状数组练习

    题目链接   https://vjudge.net/problem/34215/origin 这个题就是线段树裸题,有两种操作,实现单点更新和区间和的查找即可,这里第一次学习使用树状数组完成. 二者相 ...

  5. UVALive - 3938 Ray, Pass me the dishes!

    注意分清三种情况,并且保证字典序最小 #include <cstdio> #include <cstring> #include <algorithm> #incl ...

  6. UVA 12501 Bulky process of bulk reduction ——(线段树成段更新)

    和普通的线段树不同的是,查询x~y的话,给出的答案是第一个值的一倍加上第二个值的两倍一直到第n个值的n倍. 思路的话,就是关于query和pushup的方法.用一个新的变量sum记录一下这个区间里面按 ...

  7. UVa 1471 Defense Lines - 线段树 - 离散化

    题意是说给一个序列,删掉其中一段连续的子序列(貌似可以为空),使得新的序列中最长的连续递增子序列最长. 网上似乎最多的做法是二分查找优化,然而不会,只会值域线段树和离散化... 先预处理出所有的点所能 ...

  8. UVA 12086 Potentiometers(线段树裸题)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  9. 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations

    题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...

最新文章

  1. 这交互炸了 - 收藏集 - 掘金
  2. SilverLigth的Chart不要图例(Legend)的方法
  3. wxWidgets:wxMenuItem类用法
  4. SAP Spartacus B2B页面unit tree取数据的设计逻辑
  5. mongodb插入速度每秒_MongoDB事实:商品硬件上每秒插入80000次以上
  6. [html] 如何放大点击的区域?
  7. [手把手教]discuzX2插件制作教程__最菜鸟级别的入门坎 【三】
  8. 在 TMG 更新中心中使用 WSUS进行每日的定义更新
  9. php 数组作用域,如何在php中访问私有作用域命名空间数组数据?
  10. Netty工作笔记0053---Netty核心模块梳理
  11. 《C++程序设计语言(特别版)》——忠告
  12. CAS Tomcat实现单点登录
  13. java opencv去除干扰线_电子产品硬件研发—提高抗干扰性能的常用方法
  14. 网络规划设计方案(模板)
  15. 【工具向】分析FGUI依赖关系工具
  16. QImage类详解(QImage类型转换、QImage类函数及QImage像素操作)
  17. win10系统升级后mysql找不到服务及数据消失问题
  18. 混合颜色带(基础篇)
  19. char *与char []的区别
  20. JRE和JDK的区别?

热门文章

  1. React Native Keyboard使用详解
  2. 句句真研—每日长难句打卡Day12
  3. 为什么在加油站上班,一个月休3天,工资2000元,却有人干?
  4. 在什么情况下自己应该辞职走人了,而不是等领导下“逐客令”?
  5. 实体店想多赚钱就要学会互联网思维
  6. 人赚钱多少的本质区别在于:出售自己时间的方法不同
  7. K8S - 为 Docker 而生
  8. 中国的电商发展迅速,有了取代实体的趋势
  9. 关于计算性能的若干重要事实
  10. 手机老是应用无响应是怎么回事?