COJ 2004 序列
传送门:http://oj.cnuschool.org.cn/oj/home/addSolution.htm?problemID=978
试题描述:
WZJ的数字游戏又开始了。他写了N个自然数Ai到黑板上,让你选取一个起点L和一个终点R使sum(L,R)*min(L,R)最大,请你输出这个最大值。
sum(L,R)表示AL一直加到AR之和,min(L,R)表示AL到AR的最小值。
输入:
第一行为一个正整数N。
接下来为N个自然数Ai。
输出:
输出最大值。
输入示例:
7
1 5 2 0 5 5 7
输出示例:
85
其他说明:
1<=N<=100000
0<=Ai<=1000000
题解:
思路1:枚举所有的最小值,用单调栈或二分RMQ维护一下往前到哪里往后到哪里,然后乱搞答案。
单调栈32ms最快:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; inline void read(int& x)
{
x = ;
int sig = ;
char ch = getchar();
while(!isdigit(ch))
{
if(ch == '-') sig = -;
ch = getchar();
}
while(isdigit(ch))
{
x = x * + ch - '';
ch = getchar();
}
x *= sig;
return ;
} const int maxn = + ; int A[maxn];
int L[maxn], R[maxn]; int S[maxn]; long long v[maxn], ans; int main()
{
int n;
read(n); int top = ; for(int i = ; i <= n; i++)
{
read(A[i]);
v[i] = v[i - ] + A[i];
} A[] = A[n + ] = -;
S[++top] = ; for(int i = ; i <= n; i++)
{
while(A[S[top]] >= A[i]) top--;
L[i] = S[top] + ;
S[++top] = i;
} S[top = ] = n + ; for(int i = n;i ; i--)
{
while(A[S[top]] >= A[i]) top--;
R[i] = S[top] - ;
S[++top] = i; ans = max(ans, A[i] * (v[R[i]] - v[L[i] - ]));
} printf("%lld", ans); return ;
}
由于每一个元素只进入单调栈一次,所以是o(n)的。
RMQ157ms最慢:
#include <iostream>
#include <cstdio>
using namespace std; const int maxn = + ; int A[maxn]; int n; int log[maxn], d[maxn][]; long long ans, S[maxn]; int f1[maxn], f2[maxn]; void RMQ_init()
{
log[] = -; //你大爷
for(int i = ; i <= n; i++)
{
d[i][] = A[i];
log[i] = log[i >> ] + ;
} for(int j = ; ( << j) <= n; j++)
for(int i = ; i + ( << j) - <= n; i++) //你大爷
d[i][j] = min(d[i][j - ], d[i + ( << (j - ))][j - ]); return ;
} int query(int L, int R)
{
int k = log[R - L + ];
return min(d[L][k], d[R - ( << k) + ][k]);
} int main()
{
int m, L, R, M;
scanf("%d", &n); for(int i = ; i <= n; i++)
{
scanf("%d", &A[i]);
S[i] = S[i - ] + A[i];
} RMQ_init(); for(int i = ; i <= n; i++)
{
L = ;
R = i; while(L < R)
{
M = L + R >> ;
if(query(M, i) == A[i]) R = M;
else L = M + ;
} f1[i] = L;
} for(int i = ; i <= n; i++)
{
L = i;
R = n + ; while(L + < R)
{
M = L + R >> ;
if(query(i, M) == A[i]) L = M;
else R = M;
} f2[i] = L;
} for(int i = ; i <= n; i++)
ans = max(ans, (S[f2[i]] - S[f1[i] - ]) * A[i]); printf("%lld\n", ans); return ;
}
RMQ初始化o(nlogn),查询o(nlogn)。
思路2:将A[i]从大到小排,用并查集维护每个元素的集合,每次将该元素左右的不小于该元素本身的元素合并进来,更新答案。
正确性有待考察……以后补……
并查集47ms还可以:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; const int maxn = + ;
int f[maxn], Min[maxn];
long long Sum[maxn], _max = ;
int n, P[maxn]; struct Node{
int v, id;
bool operator < (const Node& ths) const{
return v < ths.v;
}
}A[maxn]; void read(int& x){
x = ;
int sig = ;
char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') sig = -;
ch = getchar();
}
while(isdigit(ch)){
x = * x + ch - '';
ch = getchar();
}
x *= sig;
return ;
}
void input(){
read(n);
for(int i = ; i <= n; i++) read(P[i]), A[i].id = f[i] = i, A[i].v = Min[i] = Sum[i] = P[i];
return ;
}
int findset(int x){
return f[x] == x ? x : f[x] = findset(f[x]);
}
void merge(int d1, int d2){
int f1 = findset(d1);
int f2 = findset(d2);
if(f1 != f2){
Sum[f1] += Sum[f2];
Min[f1] = min(Min[f1], Min[f2]);
f[f2] = f1;
_max = max(_max, Sum[f1] * Min[f1]);
}
return ;
}
void work(){
sort(A + , A + + n);
for(int i = n; i; i--){
int x = A[i].id;
if(x != && P[x] <= P[x - ]) merge(x, x - );
if(x != n && P[x] <= P[x + ]) merge(x, x + );
}
return ;
}
void output(){
printf("%lld\n", _max);
return ;
}
int main(){
input();
work();
output();
return ;
}
排序o(nlogn),扫描o(n),感觉很不错啊。
COJ 2004 序列的更多相关文章
- [C++]环状序列(CircularSequence,ACM/ICPC Seoul 2004,UVa1584)
Question 例题3-5 环状序列(CircularSequence,ACM/ICPC Seoul 2004,UVa1584) 长度为n的环状串有n种表示方法,分别为从某个位置开始顺时针得到,在这 ...
- 黄源河《左偏树的应用》——数字序列(Baltic 2004)
这道题哪里都找不到. [问题描述] 给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| ...
- 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)
长度为n的环状串有n种表示法,分别为从某 个位置开始顺时针得到.例如,图3-4的环状串 有10种表示: CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等. 在这些表示法中,字典序最小 ...
- [csu/coj 1078]多个序列的最长公共子序列
题意:给n个序列,同一个序列里面元素互不相同,求它们的最长公共子序列. 思路:任取一个序列,对于这个序列里面的两个数ai,aj(i<j),如果对于其它每一个序列,都出现过ai,aj,且ai在aj ...
- luogu 4331 [BalticOI 2004]Sequence 数字序列
LINK:数字序列 这是一道论文题 我去看了一眼论文鸽的论文. 发现讲的还算能懂.可并堆的操作也讲的比较清晰. 对于这道题首先有一个小trick 我们给a数组全部减去其对应的下标这样我们求出来的b数组 ...
- 搜索引擎case︱从搜索序列文本看高端商务车︱统计之都
朱雪宁(北京大学光华管理学院) 王汉生(北京大学光华管理学院) 摘要:本文对100万搜索引擎用户的13亿搜索序列文本进行探索分析,对高端车用户以及商学院人群做了描述对比,并 ...
- codevs 1058 合唱队形 2004年NOIP全国联赛提高组
1058 合唱队形 2004年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description N位同学站成一排,音 ...
- 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]
题目传送门 数字序列 题目描述 给定一个整数序列 a1,a2,⋅⋅⋅,an ,求出一个递增序列 b1<b2<⋅⋅⋅<bn ,使得序列 ai 和 bi 的各项之差的绝对 ...
- 孤荷凌寒自学python第十天序列之字符串的常用方法
孤荷凌寒自学python第十天序列之字符串的常用方法 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python的字符串操作方法非常丰富,原生支持字符串的多种操作: 1 查找子字符串 str ...
随机推荐
- 使用fastjson前台报406的问题解决方法
返回的json数据前台页面报406,而后台没有报错,下面为解决方法 <?xml version="1.0" encoding="UTF-8"?> & ...
- Web的鼠标拖动效果
以前写过一个拖动效果的Demo,拖拽元素新位置的计算是放在拖拽元素的mousemove事件中进行的.计算效率差,而且效果不好.所以一直有想怎样才能做出jquery-ui那种顺滑的拖拽效果. 其实顺滑的 ...
- rabbitMQ实战(一)---------使用pika库实现hello world
rabbitMQ实战(一)---------使用pika库实现hello world 2016-05-18 23:29 本站整理 浏览(267) pika是RabbitMQ团队编写的官方Pyt ...
- 10.3 noip模拟试题
希望[题目描述]网页浏览器者有后退与前进按钮,一种实现这两个功能的方式是用两个栈,“前进栈”.“后退栈”.这里你需要实现以下几个功能:BACK: 如果“后退栈”为空则忽略此命令. 否则将当前两面压入“ ...
- SQL Server 事务、异常
转自: http://www.cnblogs.com/moss_tan_jun/archive/2011/11/26/2263988.html 事务 在数据库中有时候需要把多个步骤的指令当作一个整 ...
- 解决dispaly:inline-block 遗留间隙的问题
今天做一个项目 .本来我打算是作成表格的 ,后来觉得太费事直接搞成一个div 里面直接放四个a ,然后我将a 设置成inline-block.刚开始还没发现任何间隙问题,(对了说到这里 博主给新手介绍 ...
- 怎样使用svn开发项目
那么首先什么是svn呢?官方有很好的解释,我说一下个人简单的理解,svn就是开源的版本控制软件, 那么什么是版本呢?简单的说版本就是标记,比如你买了一本书,同样的书名,但是版本不一定一样, 因为里面可 ...
- 快速打出System.out.println("");
sysout---->Alt+/--->System.out.println():
- 多线程lock(instance)中instance的选择.
如我的提问:http://bbs.csdn.net/topics/390496351?page=1#post-394837834 拥有类原子功能的类: class ShareState { //原子功 ...
- (转)asp.net分页存储过程
Asp.Net分页存储过程 SQL分页语句 一.比较万能的分页: sql代码: 1 2 3 select top 每页显示的记录数 * from topic where id not in (sel ...