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

好多题解里都提到了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 + ;
const int Fix = 1e5; int n, qn, a[N], head[N << ], 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 = ; char ch = ; int op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
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 << ]; #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].htag inline 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) = ;
} 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 + , 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 = ;
if(x <= mid) chkMax(res, query(lc, l, mid, x, y));
if(y > mid) chkMax(res, query(rc, mid + , r, x, y));
return res;
} } using namespace SegT; int main() {
read(n);
for(int i = ; i <= n; i++) {
read(a[i]);
pre[i] = head[a[i] + Fix];
head[a[i] + Fix] = i;
} read(qn);
for(int i = ; i <= qn; i++) {
read(q[i].l), read(q[i].r);
q[i].id = i, q[i].res = 0LL;
} sort(q + , q + + qn);
for(int j = , i = ; i <= qn; i++) {
for(; j <= q[i].r && j <= n; j++)
modify(, , n, pre[j] + , j, 1LL * a[j]);
ll now = query(, , n, q[i].l, q[i].r);
q[q[i].id].res = now;
} for(int i = ; i <= qn; i++)
printf("%lld\n", q[i].res); return ;
}

SP1557 GSS2 - Can you answer these queries II的更多相关文章

  1. SP1557 GSS2 - Can you answer these queries II(线段树)

    传送门 线段树好题 因为题目中相同的只算一次,我们可以联想到HH的项链,于是考虑离线的做法 先把所有的询问按$r$排序,然后每一次不断将$a[r]$加入线段树 线段树上维护四个值,$sum,hix,s ...

  2. SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

    GSS2 - Can you answer these queries II #tree Being a completist and a simplist, kid Yang Zhe cannot ...

  3. bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

    2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145 ...

  4. spoj gss2 : Can you answer these queries II 离线&&线段树

    1557. Can you answer these queries II Problem code: GSS2 Being a completist and a simplist, kid Yang ...

  5. SPOJ GSS2 Can you answer these queries II

    Time Limit: 1000MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description Being a ...

  6. SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)

    都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...

  7. SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树

    传送门 题意:给出一个长度为$N$的数列,$Q$次询问,每一次询问$[l,r]$之间的最大子段和,相同的数只计算一次.所有数字的绝对值$\leq 10^5$ GSS系列中不板子的大火题,单独拿出来写 ...

  8. SPOJ GSS2 Can you answer these queries II ——线段树

    [题目分析] 线段树,好强! 首先从左往右依次扫描,线段树维护一下f[].f[i]表示从i到当前位置的和的值. 然后询问按照右端点排序,扫到一个位置,就相当于查询区间历史最值. 关于历史最值问题: 标 ...

  9. BZOJ2482: [Spoj1557] Can you answer these queries II

    题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值 ...

随机推荐

  1. 微型 Python Web 框架: Bottle

    微型 Python Web 框架: Bottle 在 19/09/11 07:04 PM 由 COSTONY 发表 Bottle 是一个非常小巧但高效的微型 Python Web 框架,它被设计为仅仅 ...

  2. RMAN 增量备份 脚本

    ################################################################## ##    rman_backup.sh              ...

  3. [Err] 1067 - Invalid default value for 'xxxTime'

    下面是导入sql脚本的的局部脚本 `xxxTime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 发现是NO_ZERO_IN_DATE,NO_Z ...

  4. javabrideg的使用实践

    (1)进入这个网站http://sourceforge.net/projects/php-java-bridge/files,选择Binary package,然后选择最新的版本Php-java-br ...

  5. bzoj 2878 [Noi2012]迷失游乐园——树上的期望dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2878 很好的树上概率题的思路,就是分成up和down. 代码中有众多小细节.让我弃疗好几天的 ...

  6. Java基础知识复习(二)

    Java 重写(Override)与重载(Overload) 重写 是子类对父类的允许访问的方法的实现过程进行重新编写,返回值和形参都不能改变,属于编译时多态.即外壳不变,核心重写! 重写的好处在于子 ...

  7. Dev控件类似于ComBox的DropDownControl用法

    dropDownButton1.DropDownControl= CreateDXPopupMenu(); private DXPopupMenu CreateDXPopupMenu() { DXPo ...

  8. Deep Learning 学习笔记(6):神经网络( Neural Network )

    神经元: 在神经网络的模型中,神经元可以表示如下 神经元的左边是其输入,包括变量x1.x2.x3与常数项1, 右边是神经元的输出 神经元的输出函数被称为激活函数(activation function ...

  9. js 正则匹配 小结

    JS的正则表达式 rge.test(str) 检验目标对象中是否包含匹配模式,并相应的返回true或false   rge.source str.search(rge) 将返回一个整数值,指明这个匹配 ...

  10. 分布式爬虫搭建系列 之三---scrapy框架初用

    第一,scrapy框架的安装 通过命令提示符进行安装(如果没有安装的话) pip install Scrapy 如果需要卸载的话使用命令为: pip uninstall Scrapy 第二,scrap ...