Week5作业ABC

题目A:
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分。

Input
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,你可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。
Output
对于每组测试数据输出一行一个整数表示答案。
Example:

input:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
output:
8
4000

我的思路:
利用单调栈算法,从第一个点开始,将其与之前的比较,然后用st[r]来储存这个点能延伸到最右边的位置但会有一些数没有得到最右边的位置,即R[i],因为会被他后面的从后往前遍历的一个大于它的数阻挡,故之前的那些数都没有R[i]值,或者说是初始值0,所以他们的值可以贯穿整个右边,R[i]即为n。
然后对于其左端点,可以将原数组逆序,然后相同的方法,得其左端点,这样得到的下标并不是原来的下标,故需转化一下。
最后,遍历所有点,底乘高取最大即可。

代码:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
long long a[100001];
long long b[100001];
int n;
long long st[100001];
long long R[100001];
long long L[100001];
long long ans=-1;
long long MAX(long long a,long long b)
{
	return a>=b?a:b;
}
void solve1(){
	memset(st,0,sizeof(st));
	int l = 1, r = 0; // r-l+1 = 0
	for(int i = 1; i <= n; i++){
		while(l <= r && a[st[r]] > a[i]){
			R[st[r]] = i-1;
			r--;
		}
		st[++r] = i;
	}
	for(int i=1;i<=n;i++)
	{
		if(R[i]==0)
		R[i]=n;
	}
}
void solve2()
{
	memset(st,0,sizeof(st));
	int l = 1, r = 0; // r-l+1 = 0
	for(int i = 1; i <= n; i++){
		while(l <= r && b[st[r]] > b[i]){
			L[st[r]] = i-1;
			r--;
		}
		st[++r] = i;
	}
	for(int i=1;i<=n;i++)
	{
		if(L[i]==0)
		L[i]=n;
	}
}
void solve3()
{
	ans=-1;
	for(int i=1;i<=n;i++)
	{
		ans=MAX(ans,(R[i]+L[n+1-i]-n)*a[i]);
	}
	cout << ans << endl;
}
int main()
{
	while(scanf("%d",&n))
	{
		if(n==0)
		break;
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(L,0,sizeof(L));
	memset(R,0,sizeof(R));
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[n+1-i]=a[i];
	}	
	solve1();
	solve2();
	solve3();
}}

题目B:
Thanks to everyone’s help last week, TT finally got a cute cat. But what TT didn’t expect is that this is a magic cat.

One day, the magic cat decided to investigate TT’s ability by giving a problem to him. That is select nn cities from the world map, and a[i]a[i] represents the asset value owned by the ii-th city.

Then the magic cat will perform several operations. Each turn is to choose the city in the interval [l,r][l,r] and increase their asset value by cc. And finally, it is required to give the asset value of each city after qq operations.

Could you help TT find the answer?

Input
The first line contains two integers n,qn,q (1≤n,q≤2⋅105)(1≤n,q≤2·105) — the number of cities and operations.

The second line contains elements of the sequence aa: integer numbers a1,a2,…,ana1,a2,…,an (−106≤ai≤106)(−106≤ai≤106).

Then qq lines follow, each line represents an operation. The ii-th line contains three integers l,rl,r and cc (1≤l≤r≤n,−105≤c≤105)(1≤l≤r≤n,−105≤c≤105) for the ii-th operation.

Output
Print nn integers a1,a2,…,ana1,a2,…,an one per line, and aiai should be equal to the final asset value of the ii-th city.

Example:

input:
4 2
-3 6 8 4
4 4 -2
3 3 1
output:
-3 6 9 2

代码:

#include<iostream>
using namespace std;
long long a[200005];
long long b[200005];
int n,l,r,q,c;
void solve()
{
	if(r==n)
	{
		b[l]+=c;
	}
	else
	{
		b[l]+=c;
		b[r+1]-=c;
	}
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		if(i==1)
		b[i]=a[i];
		else
		b[i]=a[i]-a[i-1];
	}
	for(int i=1;i<=q;i++)
	{
		scanf("%d%d%d",&l,&r,&c);
		solve();
	}
	for(int i=1;i<=n;i++)
	{
		if(i==1)
		{a[1]=b[1];cout << b[i];}
		else
		{a[i]=a[i-1]+b[i];cout << " " << a[i];
		}
	}
}

C题:
一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。

如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。

现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?

如果 s 已经平衡则输出0。
example:

input:
QWER
output:
0

代码:

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
char s[100005];
int total,sum1=0,sum2=0,sum3=0,sum4=0,ans=100005,n;
bool solve(int l,int r)
{
	total=r-l+1;
	int maxx=max(max(sum1,sum2),max(sum3,sum4));
	total-=4*maxx-n+r-l+1;
	if(total>=0&&total%4==0) return true;
	else return false;
}
void solve1()
{
	int l=0,r=-1;
	while(r<n)
	{
		//sum1=sum2=sum3=sum4=0;
		if(solve(l,r))
		{
			ans=min(ans,r-l+1);l++;
			if(ans==0)
			break;
			switch(s[l-1]){
						case 'Q':sum1++;break;
						case 'W':sum2++;break;
						case 'E':sum3++;break;
						case 'R':sum4++;break;
						}
			
		}
		else
		{
			r++;
			switch(s[r]){
						case 'Q':sum1--;break;
						case 'W':sum2--;break;
						case 'E':sum3--;break;
						case 'R':sum4--;break;
						default :break;
						}
		}
		
	}
	cout << ans << endl;
}
int main()
{
	scanf("%s",&s);
	n=strlen(s);
	for(int i=0;i<n;i++)
		{
			switch(s[i]){
						case 'Q':sum1++;break;
						case 'W':sum2++;break;
						case 'E':sum3++;break;
						case 'R':sum4++;break;
						}
		}
	//cout << n << endl;
	solve1();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值