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

好多题解里都提到了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. 【转】IUSR和IIS_IUSRS

    转自:http://blog.chinaunix.net/uid-20344928-id-3306130.html   概述   在早期的IIS版本中,随着IIS的安装,系统会创建一个IUSR_Mac ...

  2. Angular2配置文件详解

    初学接触Angular2的时候,通过ng new your-project-name 命令生成一个工程空壳,本文来介绍下每个文件的作用及含义. 先来看看src的文件目录: 文件详解 File 文件 P ...

  3. Note: log switch off, only log_main and log_events will have logs!

    真机(华为c8813)在Eclipase上测试,打不出logcat信息,只有这样的一句话:Note: log switch off, only log_main and log_events will ...

  4. Linux I2C设备驱动

    i2c设备:ts.camera.audio.gsensor.e2prom I2C基本协议: 写:开始 -> 设备地址 -> 写标志 -> 应答 -> 内部地址 -> 应答 ...

  5. Linux 应用层open调用驱动层open过程

    内核版本:3.0.8 open.close.read.write.ioctl等等都是类似. ====================================================== ...

  6. php 权限 管理

    权限的思考: https://www.jianshu.com/p/cf9077a7d38a 权限例子,用户 角色 功能 用户角色关联表 角色功能关联表 http://www.cnblogs.com/n ...

  7. gitlab的本地搭建和部署使用

    公司现在的代码管理是在公司的服务器上部署了gitlab,这样既方便协同开发,有可以很好的保护代码的安全性. 那么我们就来研究一下 如何给自己的服务器上部署gitlab吧! 学习源头:https://w ...

  8. 批处理判断是否有.net环境

    @echo off (echo 已安装.NET Framework) else (echo 未安装.NET Framework) pause>nul

  9. python开发进程:共享数据&进程池

    一,共享数据 展望未来,基于消息传递的并发编程是大势所趋 即便是使用线程,推荐做法也是将程序设计为大量独立的线程集合 通过消息队列交换数据.这样极大地减少了对使用锁定和其他同步手段的需求, 还可以扩展 ...

  10. ILMerge最佳实践

    背景 为了生成的代码更加简捷,复制方便,常常会把多个可执行文件合并成一个. 方案 Project=>Properties=>Build Events=>Edit Post-build ...