SP1557 GSS2 - Can you answer these queries II
一开始看不懂题解,看懂了题解之后觉得还是挺妙的。
好多题解里都提到了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的更多相关文章
- SP1557 GSS2 - Can you answer these queries II(线段树)
传送门 线段树好题 因为题目中相同的只算一次,我们可以联想到HH的项链,于是考虑离线的做法 先把所有的询问按$r$排序,然后每一次不断将$a[r]$加入线段树 线段树上维护四个值,$sum,hix,s ...
- 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 ...
- 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 ...
- 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 ...
- SPOJ GSS2 Can you answer these queries II
Time Limit: 1000MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description Being a ...
- SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)
都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...
- SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树
传送门 题意:给出一个长度为$N$的数列,$Q$次询问,每一次询问$[l,r]$之间的最大子段和,相同的数只计算一次.所有数字的绝对值$\leq 10^5$ GSS系列中不板子的大火题,单独拿出来写 ...
- SPOJ GSS2 Can you answer these queries II ——线段树
[题目分析] 线段树,好强! 首先从左往右依次扫描,线段树维护一下f[].f[i]表示从i到当前位置的和的值. 然后询问按照右端点排序,扫到一个位置,就相当于查询区间历史最值. 关于历史最值问题: 标 ...
- BZOJ2482: [Spoj1557] Can you answer these queries II
题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值 ...
随机推荐
- 安卓开发第一记 android stdio 安装后 新建测试项目报错
Failed to resolve:com.android.support:appcompat-v7:报错处理 你在使用android studio时是否也出现过上图的报错,你还在为它的出现烦恼? ...
- ORACLE PL/SQL编程之触发器
8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2.3 创建替代(INS ...
- 实现一个scnprinf
#include <stdio.h> #include <stdarg.h> /* 该函数ret = min(size, 实际写入长度) - 1,即ret永远小于size * ...
- linux下修改ip地址
1.more /etc/sysconfig/network-scripts/ifcfg-eth0 2.ifconfig eth0 192.168.1.211 netmask 255.255.255. ...
- hive外表parquet文件
外表关联parquet文件 1. 为什么关联了一次数据文件就不能二次被使用: 2. 为什么删除了employee,select还是可以而且有数据,1,2可能是一个问题 外表drop只是metada ...
- 《PHP对象、模式与实践》之高级特性
高级特性包括:1.静态方法和属性(通过类而不是对象来访问数据和功能)2.抽象类和接口(设计,实现分离)3.错误处理(异常)4.Final类和方法(限制继承)5.拦截器(自动委托)6.析构方法(对象销毁 ...
- Javascript 推荐一个图形化展示库
觉得这个库不错: http://almende.github.io/chap-links-library/index.html
- ILMerge最佳实践
背景 为了生成的代码更加简捷,复制方便,常常会把多个可执行文件合并成一个. 方案 Project=>Properties=>Build Events=>Edit Post-build ...
- jQuery中获取相对文档的坐标的方法是什么?
offset(),获取匹配元素在当前视口的相对偏移.返回的对象包含两个整型属性:top 和 left,以像素计.此方法只对可见元素有效. position()获取匹配元素相对定位父级的偏移.没有定位父 ...
- IDA Pro 权威指南学习笔记(六) - 次要的 IDA 显示窗口
十六进制窗口 IDA 十六进制窗口可以配置为显示各种格式,并可作为十六进制编辑器使用 默认情况下,十六进制窗口显示程序内容和列表的标准十六进制代码,每行显示 16 个字节,以及其对应的 ASCII 字 ...