传送门: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 序列的更多相关文章

  1. [C++]环状序列(CircularSequence,ACM/ICPC Seoul 2004,UVa1584)

    Question 例题3-5 环状序列(CircularSequence,ACM/ICPC Seoul 2004,UVa1584) 长度为n的环状串有n种表示方法,分别为从某个位置开始顺时针得到,在这 ...

  2. 黄源河《左偏树的应用》——数字序列(Baltic 2004)

    这道题哪里都找不到. [问题描述] 给定一个整数序列a1, a2, … , an,求一个不下降序列b1 ≤ b2 ≤ … ≤ bn,使得数列{ai}和{bi}的各项之差的绝对值之和 |a1 - b1| ...

  3. 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)

    长度为n的环状串有n种表示法,分别为从某 个位置开始顺时针得到.例如,图3-4的环状串 有10种表示: CGAGTCAGCT,GAGTCAGCTC,AGTCAGCTCG等. 在这些表示法中,字典序最小 ...

  4. [csu/coj 1078]多个序列的最长公共子序列

    题意:给n个序列,同一个序列里面元素互不相同,求它们的最长公共子序列. 思路:任取一个序列,对于这个序列里面的两个数ai,aj(i<j),如果对于其它每一个序列,都出现过ai,aj,且ai在aj ...

  5. luogu 4331 [BalticOI 2004]Sequence 数字序列

    LINK:数字序列 这是一道论文题 我去看了一眼论文鸽的论文. 发现讲的还算能懂.可并堆的操作也讲的比较清晰. 对于这道题首先有一个小trick 我们给a数组全部减去其对应的下标这样我们求出来的b数组 ...

  6. 搜索引擎case︱从搜索序列文本看高端商务车︱统计之都

    朱雪宁(北京大学光华管理学院)               王汉生(北京大学光华管理学院) 摘要:本文对100万搜索引擎用户的13亿搜索序列文本进行探索分析,对高端车用户以及商学院人群做了描述对比,并 ...

  7. codevs 1058 合唱队形 2004年NOIP全国联赛提高组

    1058 合唱队形 2004年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold   题目描述 Description N位同学站成一排,音 ...

  8. 洛谷P4331 [BOI2004] Sequence 数字序列 [左偏树]

    题目传送门 数字序列 题目描述 给定一个整数序列 a1​,a2​,⋅⋅⋅,an​ ,求出一个递增序列 b1​<b2​<⋅⋅⋅<bn​ ,使得序列 ai​ 和 bi​ 的各项之差的绝对 ...

  9. 孤荷凌寒自学python第十天序列之字符串的常用方法

    孤荷凌寒自学python第十天序列之字符串的常用方法 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python的字符串操作方法非常丰富,原生支持字符串的多种操作: 1 查找子字符串 str ...

随机推荐

  1. python-集合(第二篇(七):集合)

    第二篇(七):集合   python 集合 集合标准操作 摘要: 说明: ·类似于数学中学的集合,Python中的集合可以实现去重的功能,通过set()函数来实现: ·sets支持x in set, ...

  2. 脚本动态监控input

    Jquery $('input').bind('input propertychange', function() { //进行相关操作 }); JS if(isIE) { document.getE ...

  3. MVC中javascript直接调用Model

    最近做一个统计页面, Model从后台已经获取了数据集合,想直接在前台展示,而这个展示是需要用js生成图表的. 控制器部分代码: public ActionResult Index() { var m ...

  4. (转载)Javascript 进阶 作用域 作用域链

    载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25076713 一直觉得Js很强大,由于长期不写js代码,最近刚好温故温故. 1.J ...

  5. 查询两个日期(时间)以内的数据,between and 或 and 连>= <=,to_date()

    between and 方法 select * from kk.kkhmd where larq between(to_date('2008-9-3','yyyy-mm-dd')) and (to_d ...

  6. 【转】iOS-Core-Animation-Advanced-Techniques(二)

    原文: http://www.cocoachina.com/ios/20150104/10816.html 视觉效果和变换 (四)视觉效果 嗯,园和椭圆还不错,但如果是带圆角的矩形呢? 我们现在能做到 ...

  7. Session技术详解

    1.session简介 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务器程 ...

  8. 【POJ1442】【Treap】Black Box

    Description Our Black Box represents a primitive database. It can save an integer array and has a sp ...

  9. java dos下中文乱码

    代码如下: public class PrintString{ public static void main(String args[]){ System.out.println("\\* ...

  10. SQL中distinct的用法和left join查询的含义

    SQL中distinct的用法   1.作用于单列 2.作用于多列 3.COUNT统计 4.distinct必须放在开头 5.其他 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出 ...