[COJ0989]WZJ的数据结构(负十一)
[COJ0989]WZJ的数据结构(负十一)
试题描述
给出以下定义:
1.若子序列[L,R]的极差(最大值-最小值)<=M,则子序列[L,R]为一个均匀序列。
2.均匀序列[L,R]的权值为Sum(L,R)即序列的元素和。
现在给你一个长度为N的整数序列A,请你求出权值前K大的均匀序列,输出K行为它们的权值。
输入
第一行为两个整数N,M,K。
第二行为N个整数Ai。
输出
输出K行,第i行为第i大的均匀序列的权值。
输入示例
输出示例
数据规模及约定
1<=N,K<=100000
0<=|Ai|,M<=10^9
保证原序列至少有K个均匀序列
题解
如果确定了一个区间的左端点 x,那么显然对于均匀序列 [x, y],y 一定在区间 [L, R] 内。于是我们记状态 (x, l, r, v) 表示左端点为 x,右端点在 [l, r] 内,且最大的均匀序列权值为 v,那么我们可以预处理出对于所有的 i,(i, i, r, v) 这个状态,把它扔进堆里,然后每从堆顶取一个元素 (x, l, r, v),我们可以用 RMQ 找到最优的右端点 p(即 S[p] - S[x-1] = v,S 为前缀和),使得 p 在 [l, r] 中,那么就输出这个 v,然后把 (x, l, p - 1, v') 和 (x, p + 1, r, v'') 放入堆中(其中 v' 和 v'' 都可以由求区间内最大前缀和得到),进行 k 次即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
#define maxlog 21
#define LL long long
int n, m, k;
LL S[maxn], A[maxn]; LL mx2[maxlog][maxn];
int mx[maxlog][maxn], mn[maxlog][maxn], Log[maxn], mxp[maxlog][maxn];
void rmq_init() {
Log[1] = 0;
for(int i = 2; i <= n; i++) Log[i] = Log[i>>1] + 1;
for(int i = 1; i <= n; i++) mx[0][i] = mn[0][i] = A[i];
for(int j = 1; j < maxlog; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
mx[j][i] = max(mx[j-1][i], mx[j-1][i+(1<<j-1)]),
mn[j][i] = min(mn[j-1][i], mn[j-1][i+(1<<j-1)]);
return ;
}
void rmq_init2() {
for(int i = 1; i <= n; i++) mx2[0][i] = S[i], mxp[0][i] = i;
for(int j = 1; j < maxlog; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
if(mx2[j-1][i] > mx2[j-1][i+(1<<j-1)]) mx2[j][i] = mx2[j-1][i], mxp[j][i] = mxp[j-1][i];
else mx2[j][i] = mx2[j-1][i+(1<<j-1)], mxp[j][i] = mxp[j][i] = mxp[j-1][i+(1<<j-1)];
return ;
}
int qmx(int l, int r, int tp) {
int t = Log[r-l+1], len = (1 << t);
if(tp == 1)
return max(mx[t][l], mx[t][r-len+1]);
return mx2[t][l] > mx2[t][r-len+1] ? mxp[t][l] : mxp[t][r-len+1];
}
int qmn(int l, int r) {
int t = Log[r-l+1], len = (1 << t);
return min(mn[t][l], mn[t][r-len+1]);
} struct Node {
int x, l, r; LL v;
bool operator < (const Node& t) const { return v < t.v; }
} ;
priority_queue <Node> Q; int R[maxn];
int main() {
n = read(); m = read(); k = read();
for(int i = 1; i <= n; i++) A[i] = read(), S[i] = S[i-1] + A[i]; rmq_init(); rmq_init2();
int nl = 1, nr = 0;
for(int i = 1; i <= n; i++) {
nr++;
while(qmx(nl, nr, 1) - qmn(nl, nr) > m) nl++;
R[nl] = nr;
// printf("%d %d %d %lld\n", nl, nr, qmx(nl, nr, 2), S[qmx(nl, nr, 2)] - S[nl-1]);
// Q.push((Node){ nl, nl, nr, S[qmx(nl, nr, 2)] - S[nl-1] });
}
for(int i = 1; i <= n; i++) if(!R[i]) R[i] = R[i-1];
for(nl = 1; nl <= n; nl++) {
LL tmp = S[qmx(nl, R[nl], 2)] - S[nl-1];
Q.push((Node){ nl, nl, R[nl], tmp });
// printf("%d %d %lld\n", nl, R[nl], tmp);
}
while(k--) {
Node u = Q.top(); Q.pop();
printf("%lld\n", u.v);
int p = qmx(u.l, u.r, 2);
if(u.l < p) Q.push((Node){ u.x, u.l, p - 1, S[qmx(u.l, p - 1, 2)] - S[u.x-1] });
if(p < u.r) Q.push((Node){ u.x, p + 1, u.r, S[qmx(p + 1, u.r, 2)] - S[u.x-1] });
} return 0;
}
[COJ0989]WZJ的数据结构(负十一)的更多相关文章
- COJ 1011 WZJ的数据结构(十一)树上k大
题解:主席树&DFS序. PS:为什么我一开始Wa了N发 是因为有一个左区间我写成[L,M+1]了.......................... #include<iostream ...
- COJ969 WZJ的数据结构(负三十一)
WZJ的数据结构(负三十一) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 A国有两个主基站,供给全国的资源.定义一个主基站 ...
- COJ 0979 WZJ的数据结构(负二十一)
WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个 ...
- [COJ0985]WZJ的数据结构(负十五)
[COJ0985]WZJ的数据结构(负十五) 试题描述 CHX有一个问题想问问大家.给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L].A[L+1].…….A[R]中没有重复的数,输出R- ...
- [COJ0988]WZJ的数据结构(负十二)
[COJ0988]WZJ的数据结构(负十二) 试题描述 输入 见题目,注意本题不能用文件输入输出 输出 见题目,注意本题不能用文件输入输出 输入示例 输出示例 数据规模及约定 1≤N≤1500,M≤N ...
- COJ966 WZJ的数据结构(负三十四)
WZJ的数据结构(负三十四) 难度级别:C: 运行时间限制:20000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给一棵n个节点的树,请对于形如"u ...
- COJ967 WZJ的数据结构(负三十三)
WZJ的数据结构(负三十三) 难度级别:C: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大 ...
- COJ970 WZJ的数据结构(负三十)
WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...
- COJ968 WZJ的数据结构(负三十二)
WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...
随机推荐
- Git.Framework 框架随手记--ORM查询数据集合 一
本文记录Git.Framework之ORM中最为浓墨重彩的一篇,查询集合.根据自己做的项目统计这个是使用频率最高的一个. 一. 查询集合方法简介 (1)List<T> GetList(); ...
- 简单统计SQLSERVER用户数据表大小(包括记录总数和空间占用情况)
在SQLSERVER,简单的组合sp_spaceused和sp_MSforeachtable这两个存储过程,可以方便的统计出用户数据表的大小,包括记录总数和空间占用情况,非常实用,在SqlServer ...
- 图解NodeJS【基于事件、回调的单线程高性能服务器】原理
刚开始了解Node感觉很吊,各种说高性能,可是一直不理解为什么单线程会比多线程快?为什么异步IO比非阻塞IO快?因此,本篇在阅读相关书籍后,根据自己的理解,整理此文,如有错误,仅代表理论不精,必当修改 ...
- 【CodeForces 620D】Professor GukiZ and Two Arrays
题 题意 两个数列,一个有n个数,另一个有m个数,让你最多交换两次两个数列的数,使得两个数列和的差的绝对值最小,求这个差的绝对值.最少交换次数.交换数对 分析 交换0次.1次可得到的最小的差可以枚举出 ...
- 【Matplotlib】绘图常见设置说明
说明:此贴会不定期进行更新! 设置1:图像的大小设置. 如果已经存在figure对象,可以通过以下代码设置尺寸大小: f.set_figheight(15) f.set_figwidth(15) 若果 ...
- MyEclipse护眼模式、字体大小的调整
1.Eclipse改变背景颜色 Windows menu --> Preference General -> Editors -> Text Editors(click), 在底部 ...
- BZOJ1045 [HAOI2008] 糖果传递
Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数n<=987654321,表示小朋友的个数 ...
- SPOJ Pouring Water
传送门 POUR1 - Pouring water #gcd #recursion Given two vessels, one of which can accommodate a litres o ...
- Android:Touch和Click的区别
http://blog.csdn.net/hufeng882412/article/details/7310142 针对屏幕上的一个View控件,Android如何区分应当触发onTouchEvent ...
- Linux下tomcat作为守护进程运行(开机启动、以指定的用户运行、解决非root身份不能绑定1024以下端口的问题)的配置方法
如题. 参考资料: http://www.jdiy.org/read.jd?id=y0haaynq1w http://blog.csdn.net/shw2004/article/details/578 ...