B、题目链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2326
思路:要求一段连续区间内的最大长方形面积,我们可以用dp[i]数组表示长度为i的区间的最大长方形面积,每次更新数组,直到求出最大值。重点是如何无更新呢???我们用a[i]表示这一段区间的最大值,向两边更新区间的最小值,然后要求的面积就是min*区间长度,更新完找个最大的就是答案。
可能是这道题的数据比较水,HDU 1506基本上是一样的题,暴力直接找会超时,还需要用到单调栈,时间复杂度是O(n).
CODE1:(暴力)
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#include<queue>
#include<stack>
#include<string.h>
typedef long long LL;
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=100005;
const double eps=0.0001;
LL a[maxn],dp[maxn];//dp[i]表示区间长度为i时能得到的最大值
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
LL maxx=0;
for(int i=1;i<=n;i++)
{
dp[1]=max(dp[1],a[i]);
LL minn=a[i];
int l,r;
l=r=i;
while(true)
{
if(r-l+1>=n)//如果找完了,跳出
break;
if(l!=1&&(r==n||a[l-1]>a[r+1]))
minn=min(minn,a[--l]);
else
minn=min(minn,a[++r]);
if(a[i]<a[l]||a[i]<a[r])//如果a[i]不是这段区间的最大值,跳出
break;
dp[r-l+1]=max(dp[r-l+1],minn*(r-l+1));
}
}
for(int i=1;i<=n;i++)
maxx=max(maxx,dp[i]);
printf("%lld\n",maxx);
}
return 0;
}
CODE2:单调栈
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#include<queue>
#include<stack>
#include<string.h>
typedef long long LL;
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=100005;
const double eps=0.0001;
struct node
{
LL h,w;
} c[maxn];
stack<node>s;
int main()
{
int n;
while(~scanf("%d",&n))
{
LL ans=0,cnt=0;
while(!s.empty())
s.pop();
c[0].h=0;
c[0].w=0;
s.push(c[0]);
for(int i=1; i<=n; i++)
{
scanf("%d",&c[i].h);
c[i].w=1;
}
for(int i=1; i<=n; i++)
{
if(c[i].h>s.top().h)
{
c[i].w=1;
s.push(c[i]);
}
else
{
cnt=0;
while(!s.empty()&&s.top().h>c[i].h)
{
ans=max(ans,(cnt+s.top().w)*s.top().h);
cnt+=s.top().w;
s.pop();
}
c[i].w=cnt+1;
s.push(c[i]);
}
}
cnt=0;
while(!s.empty())
{
ans=max(ans,(cnt+s.top().w)*s.top().h);
cnt+=s.top().w;
s.pop();
}
printf("%lld\n",ans);
}
return 0;
}
这道题和HDU 5696区间的价值类似(题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5696),区间价值 这道题就是求区间1~n内,区间长度为i的最大值和最小值的最大乘积,思路基本上是一样,更新的时候是:
dp[r-l+1]=max(dp[r-l+1],minn*a[i]); 前一段时间刚做过这道题,还有点印象,不过还是卡了一会。。。
G、题目链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2331
思路:与、或、异或都与二进制有关,我们可以从这个角度出发去解决问题。
当时题面改了之后没看太懂题目,去讨论区看了一下才测地明白题意,就是从[0,m]之间找出一个数,使它按给定的顺序运算下去结果最大,输出最大的结果,看明白题意之后就暴力写了一发,跑出来样例,并没有敢交,结果肯定会超时,然后就想了好一会,想到二进制,用小于m的2的i次方去找结果,过了样例,直接就交了,WA,呜呜~~(>_<)~~~~,不知道为啥,这时比赛已经快结束了,抱着试一试的心态又判了2^i-1,2^i+1(结果不对,肯定是判的 少 了,毕竟吧【0,m】个数变成了几个数,就多判了几个),对结果找一个最大的,竟然过了,好开心,不知道原理是什么,就这样神奇的过了,多猜猜还是有好处的,嘿嘿,,不过还是要自己理解。
CODE:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#include<queue>
#include<stack>
#include<string.h>
typedef long long LL;
using namespace std;
#define INF 0x3f3f3f3f
const int maxn=100005;
const double eps=0.0001;
struct node
{
char s[15];
int x;
}c[maxn];
int a[32];
void init()
{
a[0]=1;
for(int i=1;i<32;i++)
a[i]=a[i-1]*2;
}
int main()
{
int n,m;
init();
while(~scanf("%d%d",&n,&m))
{
int maxx=0;
for(int i=0;i<n;i++)
scanf("%s%d",c[i].s,&c[i].x);
for(int i=0;a[i]<=m;i++)
{
int xx=a[i],yy=a[i]-1,zz=a[i]+1;
for(int j=0;j<n;j++)
{
//cout<<c[j].s<<" "<<c[j].x<<endl;
if(c[j].s[0]=='A')
{
xx=xx&c[j].x;
yy=yy&c[j].x;
zz=zz&c[j].x;
}
else if(c[j].s[0]=='O')
{
xx=xx|c[j].x;
yy=yy|c[j].x;
zz=zz|c[j].x;
}
else if(c[j].s[0]=='X')
{
xx=xx^c[j].x;
yy=yy^c[j].x;
zz=zz^c[j].x;
}
}
maxx=max(maxx,max(xx,max(yy,zz)));
}
printf("%d\n",maxx);
}
return 0;
}
经过了天梯赛,慢慢开始学会了在没有思路的情况下,凭着感觉大胆的去猜,这样思路打开的才会更快。每天进步一点点,就会有很大的飞跃。