作业Week5
A-最大矩形
1.题意:给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分。
Input:
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,你可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。
Output:
对于每组测试数据输出一行一个整数表示答案。
2.思路:首先,我们注意到该题hi的范围是0~1000000000,所以数据类型应选用long long int,而不是int。要计算出矩形的最大面积,我们要计算出最大高度对应的最大宽度,由此可以计算出各个高度所对应的面积。我们可以用单调递增栈来计算出各高度对应的最大宽度,同时,栈内元素表示的是具体不同高度所对应的下标,故每当有元素出栈时,就可计算出栈顶元素对应高度的最大矩形面积,最后,再计算出各个面积的最大值便可得到答案。另,为了保证各高度均能从栈内弹出,可以向元素底加入一个0,从而确保。
3.代码:
#include <iostream>
#include <stack>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n;
while(1)
{
cin>>n;
if(n==0)
return 0;
long long int* a=new long long int[n+1];
for(int i=0;i<n;i++)
cin>>a[i]; a[n]=0;
stack<int> st;
long long int area=0, b=0;
int m=0;
for(int i=0;i<=n;i++)
{
if(!st.empty()) m=st.top();
while(!st.empty()&&a[i]<a[m])
{
m=st.top();
st.pop();
if(!st.empty())
b=a[m]*(i-st.top()-1);
else
b=a[m]*i;
if(!st.empty())
m=st.top() ;
area=max(b,area);
}
st.push(i);
}
cout<<area<<endl;
}
}
B-TT’s Magic Cat
1.题意:现有一个长度为n的数组,现对其进行q次操作,每次操作给出L、R、c,表示区间【L,R】中的每个数均加上c,求q次操作后,区间中每个元素的值。
example:
input:
4 2 //数组中元素的个数和q
-3 6 8 4 //原数组
4 4 -2 //区间[4,4]中的元素每个数加上-2
3 3 1 //区间[3,3]中的每个元素加上1
output:
-3 6 9 2 //最终结果
2.思路:一开始把该题看得过于简单,使用了最笨的方法,挨个遍历,结果递交发现超时。为了避免超时,我们可以将原数组转换为差分数组,将区间修改转变为单点修改,即将a[L,R]=a[L,R]+c转换为b[L]=b[L]+c, b[R+1]=b[R+1]-c,b数组前缀和即为a数组最终数值,可通过a[i]=a[i-1]+b[i]计算出最终答案。
总结:课堂上讲到的每一个知识点都必定有它的用处,对于每一个点都要尽量去掌握,可以大大提高自己的代码效率。
3.代码:
#include <iostream>
#include <stdio.h>
using namespace std;
long long int a[1000000];
long long int b[1000000];
int main()
{
int n,q;
cin>>n>>q;
a[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i]-a[i-1];
}
for(int i=q;i>0;i--)
{
int l,r,c;
cin>>l>>r>>c;
b[l]=b[l]+c;
b[r+1]=b[r+1]-c;
}
for(int i=1;i<=n;i++)
{
a[i]=b[i]+a[i-1];
cout<<a[i]<<" ";
}
cout<<endl;
}
C-平衡字符串
1.题意:一个长度为 n 的字符串 s,其中仅包含 ‘Q’, ‘W’, ‘E’, ‘R’ 四种字符。
如果四种字符在字符串中出现次数均为 n/4,则其为一个平衡字符串。
现可以将 s 中连续的一段子串替换成相同长度的只包含那四个字符的任意字符串,使其变为一个平衡字符串,问替换子串的最小长度?
如果 s 已经平衡则输出0。
example:
Input
QWER
Output
0
Input
QQWE
Output
1
Input
QQQW
Output
2
Input
QQQQ
Output
3
2.思路:本题使用尺取法。给定区间[L, R],用sum1、sum2、sum3、sum4四个数来计算不包含区间[L, R]这一段时,字符’Q’, ‘W’, ‘E’, 'R’的个数,通过替换使4类字符数量一致,再判断剩余空闲位置是否是4的倍数
MAX = max(sum1, sum2, sum3, sum4)
TOTAL = R – L + 1
BALANCE = TOTAL -[(MAX-sum1)+(MAX-sum2)+(MAX-sum3)+(MAX-sum4)]
如果BALANCE>=0且为4的倍数,则满足条件,反之不满足。根据尺取法,如果当前[L, R]满足要求,则L++;如果不满足要求,则R++。之后我们还要从前往后遍历整个数组即可得出最小的TOTAL。
3.代码:
#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int a,b,c,d;
string s;
bool judge(int l,int r,int bal)
{
int a1=0,b1=0,c1=0,d1=0;
for(int i=l;i<=r&&bal!=0;i++)
{
if(s[i]=='Q')
a1++;
else if(s[i]=='W')
b1++;
else if(s[i]=='E')
c1++;
else if(s[i]=='R')
d1++;
}
a1=a-a1,b1=b-b1,c1=c-c1, d1=d-d1;
int Max=max(a1, b1);
Max=max(Max, c1);
Max=max(Max, d1);
int tal=r-l+1;
int sum=Max*4-a1-b1-c1-d1;
int res=tal-sum;
if(res<0||res%4!=0)
return 0;
else
return 1;
}
int main()
{
cin>>s;
a=0,b=0,c=0,d=0;
for(int i=0;i<s.length();i++)
{
if(s[i]=='Q')
a++;
else if(s[i]=='W')
b++;
else if(s[i]=='E')
c++;
else if(s[i]=='R')
d++;
}
int l=0,r=0,balance=s.length();
if(judge(0,0,0))
{
cout<<"0"<<endl;
return 0;
}