延绵的山峰 ★★☆ 输入文件:climb.in 输出文件:climb.out 简单对比 时间限制:1 s 内存限制:512 MB 问题描述 有一座延绵不断、跌宕起伏的山,最低处海拔为0,最高处海拔不超过8848米,从这座山的一端走到另一端的过程中,每走1米海拔就升高或降低1米。有Q个登山队计划在这座山的不同区段登山,当他们攀到各自区段的最高峰时,就会插上队旗。请你写一个程序找出他们插旗的高度。 输入文件 第1行,一个整数N(N<=10^6),表示山两端的跨度。 接下来N+1行,每行一个非负整数Hi,表示该位置的海拔高度,其中H0=Hn=0。 然后是一个正整数Q(Q<=7000),表示登山队的数量。 接下来Q行,每行两个数Ai, Bi,表示第i个登山队攀爬的区段[Ai,Bi],其中0<=Ai<=Bi<=N。 输出文件 Q行,每行为一个整数,表示第i个登山队插旗的高度。 样例输入 10 0 1 2 3 2 3 4 3 2 1 0 5 0 10 2 4 3 7 7 9 8 8 样例输出 4 3 4 3 2
/*
还是裸题.
维护max.
不过第一次RE了.
原因是line :
for(
int i=
0;i<=n;i++)
然后改成了
for(
int i=
0;i<=n-mi[j-
1];i++).
因为[n-mi[j-
1],n]这一块对答案是没有贡献的.
这样的话就算上n后面的贡献了.
要是求min就尴尬了.
*/
using namespace std;
int n,
m,a[MAXN],f[MAXN][D+
5],mi[D+
5];
int read()
{
int x=
0,f=
1;char ch=getchar();
while(ch<
'0'||ch>
'9'){
if(ch==
'-')f=-
1;ch=getchar();}
while(ch>=
'0'&&ch<=
'9')
x=
x*10+ch-
48,ch=getchar();
return x*f;
}
void slove()
{
int k=
log(n)/
log(
2)+
1;
for(
int j=
1;j<=k;j++)
for(
int i=
0;i<=n-mi[j]+
1;i++)//
1 R.
f[i][j]=max(f[i][j-
1],f[i+mi[j-
1]][j-
1]);
return ;
}
int query(
int l,
int r)
{
int k=
log(r-l+
1)/
log(
2);
return max(f[l][k],f[r-mi[k]+
1][k]);
}
int main()
{
freopen(
"climb.in",
"r",stdin);
freopen(
"climb.out",
"w",stdout);
int x,
y;
n=
read();mi[
0]=
1;
for(
int i=
1;i<=D;i++) mi[i]=mi[i-
1]<<
1;
for(
int i=
0;i<=n;i++) a[i]=
read(),f[i][
0]=a[i];
slove();
m=
read();
while(
m--)
{
x=
read(),
y=
read();
printf(
"%d\n",query(
x,
y));
}
return 0;
}
转载请注明原文地址: https://ju.6miu.com/read-659241.html