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 ...
随机推荐
- JAVA学习:方法
方法是放在两个不同的java文件中,一个是指存储相应的业务逻辑, 另一个java文件是只控制 输入输出(也就是用户界面). Calc方法: /* * 方法 */ public class Calc { ...
- windows10UWP:Segoe MDL2 图标指南
windows10 UWP 开发中,图标的使用非常广泛.为此,微软建议大家使用 Segoe MDL2 Assets 字体来获取图标.Segoe MDL2 Assets 包括了哪里图标,微软在 http ...
- Sqlserver通过链接服务器访问Oracle
工作中遇到的情况,win 7 64位操作系统的就安装64位的oracle 客户端,然后重启sql service服务后再创建sql 链接服务器.关于如何创建链接服务器请查看下面的大神的链接: http ...
- SpringMVC4+thymeleaf3的一个简单实例(篇三:页面参数获取)
本篇将通过示例介绍页面参数是如何传递到后台的.我们继续沿用之前搭好的程序结构,如果你不知道,请参照前两篇.为方便跳转页面,我们在首页以及zoolist.html页面都加上彼此地址的链接:首页: zoo ...
- Error Creating Deployment 有关Tomcat配置问题
配置Tomcat的时候出现提示框The selected server is enabled,but is not configured properly.Deployment to it will ...
- hdoj 1686 kmp
题目: Sample Input 3 BAPC BAPC AZA AZAZAZA VERDI AVERDXIVYERDIAN Sample Output 1 3 0 代码: #in ...
- 【BZOJ3673】【可持久化并查集】可持久化并查集 by zky
Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n ...
- Windows的命令行怎么支持通配符
摸索出一个小技巧,虽然Windows的命令行本身不支持通配符,但可以在脚本里把传进来的参数当通配符用 只要加上@ARGV = glob "@ARGV";就行了 @ARGV = gl ...
- 《service》-“linux命令五分钟系列”之二
本原创文章属于<Linux大棚>博客. 博客地址为http://roclinux.cn. 文章作者为roc 希望您能通过捐款的方式支持Linux大棚博客的运行和发展.请见“关于捐款” == ...
- Linux mail 命令使用
linux mail 命令参数: 使用mail发邮件时,必须先将sendmail服务启动. mail –s “邮件主题” –c”抄送地址” –b “密送地址” -- -f 发送人邮件地址 –F 发件人 ...