一开始看不懂题解,看懂了题解之后觉得还是挺妙的。

好多题解里都提到了HH的项链,但是我觉得关系并不大啊……

先把所有询问离线下来按照右端点排序,按照询问的要求一个一个加入数字,怎么加入数字,我们设计一颗特别的线段树:

假设当前我们在$[1, r]$中已经加完了数字,那么线段树的叶子结点$l$表示$\sum_{i = l}^{r}a_i$,非叶子结点在左右儿子之间取个最大值就好了,然后我们发现这样子答案就是询问区间中曾经出现过的数的最大的一个值,我们只要把这个最大值顺便保留计算一下就好了。

考虑一下怎么添加数,对于一个下标$i$,只要在$[pre_i + 1, i]$中区间加$a_i$即可($pre_i$表示前一个$a_i$出现的位置)。

用两个标记维护当前最大值和历史最大值,实现起来有一些细节。

时间复杂度$O(nlogn)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;const int N = 1e5 + 5;
const int Fix = 1e5;int n, qn, a[N], head[N << 1], pre[N];struct Querys {int l, r, id;ll res;friend bool operator < (const Querys &x, const Querys &y) {return x.r < y.r;}} q[N];inline void read(int &X) {X = 0; char ch = 0; int op = 1;for(; ch > '9' || ch < '0'; ch = getchar())if(ch == '-') op = -1;for(; ch >= '0' && ch <= '9'; ch = getchar())X = (X << 3) + (X << 1) + ch - 48;X *= op;
}inline ll max(ll x, ll y) {return x > y ? x : y;
}template <typename T>
inline void chkMax(T &x, T y) {if(y > x) x = y;
}namespace SegT {struct Node {ll mx, tag, his, htag;inline Node (ll nowMx = 0LL, ll nowTag = 0LL, ll nowHis = 0LL, ll nowHtag = 0LL) {mx = nowMx, tag = nowTag, his = nowHis, htag = nowHtag;}} s[N << 2];#define lc p << 1#define rc p << 1 | 1#define mid ((l + r) >> 1)#define mx(p) s[p].mx#define tag(p) s[p].tag#define his(p) s[p].his#define htag(p) s[p].htaginline void up(int p) {mx(p) = max(mx(lc), mx(rc));his(p) = max(his(lc), his(rc));}inline void down(int p) {chkMax(his(lc), mx(lc) + htag(p));chkMax(his(rc), mx(rc) + htag(p));mx(lc) += tag(p), mx(rc) += tag(p);chkMax(htag(lc), tag(lc) + htag(p));chkMax(htag(rc), tag(rc) + htag(p));tag(lc) += tag(p), tag(rc) += tag(p);tag(p) = htag(p) = 0;}void modify(int p, int l, int r, int x, int y, ll v) {if(x <= l && y >= r) {mx(p) += v;chkMax(his(p), mx(p));tag(p) += v;chkMax(htag(p), tag(p));return;}down(p);if(x <= mid) modify(lc, l, mid, x, y, v);if(y > mid) modify(rc, mid + 1, r, x, y, v);up(p);}ll query(int p, int l, int r, int x, int y) {if(x <= l && y >= r) return s[p].his;down(p);ll res = 0;if(x <= mid) chkMax(res, query(lc, l, mid, x, y));if(y > mid) chkMax(res, query(rc, mid + 1, r, x, y));return res;}} using namespace SegT;int main() {read(n);for(int i = 1; i <= n; i++) {read(a[i]);pre[i] = head[a[i] + Fix];head[a[i] + Fix] = i;}read(qn);for(int i = 1; i <= qn; i++) {read(q[i].l), read(q[i].r);q[i].id = i, q[i].res = 0LL;}sort(q + 1, q + 1 + qn);for(int j = 1, i = 1; i <= qn; i++) {for(; j <= q[i].r && j <= n; j++) modify(1, 1, n, pre[j] + 1, j, 1LL * a[j]);ll now = query(1, 1, n, q[i].l, q[i].r);q[q[i].id].res = now;}for(int i = 1; i <= qn; i++)printf("%lld\n", q[i].res);return 0;
}

View Code

转载于:https://www.cnblogs.com/CzxingcHen/p/9829639.html

SP1557 GSS2 - Can you answer these queries II相关推荐

  1. GSS2 - Can you answer these queries II

    GSS2 - Can you answer these queries II 题意: 给你1e51e51e5 的序列,每次询问区间l到rl到rl到r,每个相同的数只算一次的最大子段和. 思路: 乍一眼 ...

  2. SPOJ GSS2 Can you answer these queries II (线段树离线) - xgtao -

    Can you answer these queries II 这是一道线段树的题目,维护历史版本,给出N(<=100000)个数字(-100000<=x<=100000),要求求出 ...

  3. SPOJ GSS2 Can you answer these queries II

    很好的一道题,想了很久.首先突破的是,可以找到枚举其中一边,假设是尾部y,然后快速找出满足条件的最大的头部x,连续区间的和 很容易想到借助部分和的思想,如果是从y开始往前面累加,那么就是一个关于y的后 ...

  4. Can you answer these queries II

    题意: 给一长度为n的序列,有m组询问,每一组询问给出[l,r]询问区间内的最大去重连续子段和. 解法: 考虑一下简化后的问题:如果题目要求询问查询以$r$为右端点且$l$大于等于给定值的去重连续子段 ...

  5. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  6. 线性代数四之动态DP(广义矩阵加速)——Can you answer these queries III,保卫王国

    动态DP--广义矩阵加速 SP1716 GSS3 - Can you answer these queries III description solution code [NOIP2018 提高组] ...

  7. HDU 4027 Can you answer these queries?(线段树/区间不等更新)

    传送门 Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/6576 ...

  8. HDU 1027 G - Can you answer these queries?

    http://acm.hdu.edu.cn/showproblem.php?pid=4027 Can you answer these queries? Time Limit: 4000/2000 M ...

  9. Can you answer these queries I SPOJ - GSS1 (线段树维护区间连续最大值/最大连续子段和)...

    You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| ≤ 15007 , 1 ≤ N ≤ 50000 ). A query is defi ...

最新文章

  1. Codeforces Round #395 (Div. 2)(未完)
  2. 惠普打印信息页无法连接到服务器,惠普M400系列打印机网络连接无法打印怎么办?...
  3. coming music shows
  4. 如何在ubuntu中编写python_在ubuntu下编写python(python入门)
  5. 计算机的智能化研究领域的是,科学网—第五代计算机为何在“智能化”阶段的发展像蜗牛般的徘徊前行? - 邹晓辉的博文...
  6. [安卓学习]AndroidManifest.xml文件内容详解
  7. Linux-IPC进程间通信(day11)
  8. java调用打印机没反应_java代码调用打印机没反应
  9. python 将数据库的 utc时间转换成本地时间
  10. ftp linux 推送文件_Linux文件传输FTP详解
  11. Vue入门笔记Day 8
  12. python后端开发简历分享_Python后端开发工程师面试
  13. 论文笔记 Semantics-Guided Neural Networks for Efficient Skeleton-Based Human Action Recognition - CVPR
  14. CentOS7 编译安装qbittorrent遇到的问题
  15. 什么是Arduino?Arduino的起源与架构简述
  16. [转载]巴塞罗那神圣家族教堂
  17. Cloudify Cloud foundry
  18. 1.2 pyenv使用
  19. 图解 Word2Vec
  20. 数据结构初探--什么是数据结构?

热门文章

  1. 数据库索引的数据结构b+树
  2. 2018.09.19python学习第七天part1
  3. 《Head.First设计模式读书笔记》之设计原则一、二和三
  4. varnish构建高速缓存
  5. HDFS源码分析DataXceiver之整体流程
  6. JS设置cookie,删除cookie
  7. Spring 注解方式实现 事务管理
  8. 命令行下findstr的BUG(Windows)
  9. O2O概念实践案例: Giftly改变送礼方式
  10. 一个非常实用的 div+css 实现的导航条