【BZOJ1345】[Baltic2007]序列问题Sequence 贪心+单调栈

【BZOJ1345】[Baltic2007]序列问题Sequence

Description

对于一个给定的序列a1, …, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列。这一操作的代价是max(ai,ai+1)。进行n-1次该操作后,可以得到一个长度为1的序列。我们的任务是计算代价最小的reduce操作步骤,将给定的序列变成长度为1的序列。

Input

第一行为一个整数n( 1 <= n <= 1,000,000 ),表示给定序列的长度。接下来的n行,每行一个整数ai(0 <=ai<= 1, 000, 000, 000),为序列中的元素。

Output

只有一行,为一个整数,即将序列变成一个元素的最小代价。

Sample Input

3
1
2
3

Sample Output

5

HINT

30%的测试数据 n<=500;
50%的测试数据 n <= 20,000。

题解:我们只考虑将小数合并到大数上的情况。对于一个数ai,它要么与i之前第一个>ai的数合并,要么与i之后第一个>ai的数合并,所以用单调栈维护一下,贪心地选择较小的那个即可。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=1000010;
typedef long long ll;
int n,t;
ll ans;
int v[maxn],st[maxn],ls[maxn],rs[maxn];

inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
int main()
{
	n=rd();
	int i;
	for(i=1;i<=n;i++)	v[i]=rd();
	for(t=0,i=1;i<=n;i++)
	{
		while(t&&v[st[t]]<v[i])	t--;
		ls[i]=st[t],st[++t]=i;
	}
	for(t=0,i=n;i>=1;i--)
	{
		while(t&&v[st[t]]<=v[i])	t--;
		rs[i]=st[t],st[++t]=i;
	}
	for(i=1;i<=n;i++)
	{
		if(!ls[i]&&!rs[i])	continue;
		if(ls[i]&&(!rs[i]||v[ls[i]]<v[rs[i]]))	ans+=v[ls[i]];
		else	ans+=v[rs[i]];
	}
	printf("%lld",ans);
	return 0;
}
时间: 2024-10-25 22:41:59

【BZOJ1345】[Baltic2007]序列问题Sequence 贪心+单调栈的相关文章

bzoj1345[Baltic2007]序列问题Sequence*

bzoj1345[Baltic2007]序列问题Sequence 题意: n个数,合并ai和ai+1可以得到max(ai,ai+1),代价为max(ai,ai+1).问合并n-1次最小代价为多少.n≤1000000. 题解: (来自题解,因为我不知道为什么这样做)维护一个单调递减栈.对于每个加入的元素,若加入后不满足单调性质,则让其与栈顶-1的元素比较:如果加入的数大,则合并栈顶和栈顶-1的数(把栈顶去掉),费用为栈顶-1:否则合并当前与栈顶的数(把栈顶去掉),费用为当前数.重复上述操作,直到满

单调栈 BZOJ1345 [Baltic2007]序列问题Sequence

1345: [Baltic2007]序列问题Sequence Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 899  Solved: 471[Submit][Status][Discuss] Description 对于一个给定的序列a1, -, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列.这一操作的代价是max(ai,ai+1).进行n-

【BZOJ 1345】 [Baltic2007]序列问题Sequence

1345: [Baltic2007]序列问题Sequence Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 618  Solved: 307 [Submit][Status][Discuss] Description 对于一个给定的序列a1, -, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列.这一操作的代价是max(ai,ai+1).进行

[USACO2005][POJ3044]City Skyline(贪心+单调栈)

题目:http://poj.org/problem?id=3044 题意:以坐标的形式给出一张图,表示一些楼房的正视图,求出楼房的最少个数. 分析:和小学常做的立方体问题很像,很容易想到一个贪心方法,那就是尽量把矮的楼房放在高的楼房的前面,即连续的等高的一些"X"我们把它视为一座楼房. 具体的做法可以维护一个Y坐标单增的栈,从左到右读入每个坐标,将Y坐标与栈顶坐标比较: 若Y==栈顶坐标,那么接着读下面一个坐标 若Y>栈顶坐标,那么把Y坐标加入栈成为新的栈顶 若Y<栈顶坐标

AcWing:131. 直方图中最大的矩形(贪心 + 单调栈)

直方图是由在公共基线处对齐的一系列矩形组成的多边形. 矩形具有相等的宽度,但可以具有不同的高度. 例如,图例左侧显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,矩形的宽度都为1: 通常,直方图用于表示离散分布,例如,文本中字符的频率. 现在,请你计算在公共基线处对齐的直方图中最大矩形的面积. 图例右图显示了所描绘直方图的最大对齐矩形. 输入格式 输入包含几个测试用例. 每个测试用例占据一行,用以描述一个直方图,并以整数n开始,表示组成直方图的矩形数目. 然后跟随n个整数h1,…,hn

【bzoj1345】[Baltic2007]序列问题Sequence 单调栈

题目描述 对于一个给定的序列a1, …, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列.这一操作的代价是max(ai,ai+1).进行n-1次该操作后,可以得到一个长度为1的序列.我们的任务是计算代价最小的reduce操作步骤,将给定的序列变成长度为1的序列. 输入 第一行为一个整数n( 1 <= n <= 1,000,000 ),表示给定序列的长度.接下来的n行,每行一个整数ai(0

【BZOJ】3016: [Usaco2012 Nov]Clumsy Cows 贪心 单调栈

Description Bessie the cow is trying to type a balanced string of parentheses into her new laptop, but she is sufficiently clumsy (due to her large hooves) that she keeps mis-typing characters. Please help her by computing the minimum number of chara

2019年杭电多校第二场 1002题Beauty Of Unimodal Sequence(LIS+单调栈)

题目链接 传送门 思路 首先我们对\(a\)正反各跑一边\(LIS\),记录每个位置在前一半的\(LIS\)中应该放的位置\(ans1[i]\),后一半的位置\(ans2[i]\). 对于字典序最小的方案,我们找到第一个峰值,然后往前遍历.在\(i\)这个位置,如果它在\(LIS\)中放的位置是\(pos\),那么我们先看当前放在\(pos+1\)的值是否比它大,大的话就说明这个位置一定比前面放过在\(pos\)这个位置的更优(因为字典序更小,且\([1,i]\)一定可以放满\([1,pos-1

HDU 6047 Maximum Sequence (贪心+单调队列)

题意:给定一个序列,让你构造出一个序列,满足条件,且最大.条件是 选取一个ai <= max{a[b[j], j]-j} 析:贪心,贪心策略就是先尽量产生大的,所以就是对于B序列尽量从头开始,由于数据比较大,采用桶排序,然后维护一个单调队列,使得最头上最大. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #i