蒟蒻の第一条blog~
今天听完二分和倍增,于是练课后习题。
CJOJ P1972 绵延的山峰
Description
有一座延绵不断、跌宕起伏的山,最低处海拔为0,最高处海拔不超过8848米,从这座山的一端走到另一端的过程中,每走1米海拔就升高或降低1米。有Q个登山队计划在这座山的不同区段登山,当他们攀到各自区段的最高峰时,就会插上队旗。请你写一个程序找出他们插旗的高度。
Input
第1行,一个整数N(N<=10^6),表示山两端的跨度。
接下来N+1行,每行一个非负整数Hi,表示该位置的海拔高度,其中H0=Hn=0。
然后是一个正整数Q(Q<=7000),表示登山队的数量。
接下来Q行,每行两个数Ai, Bi,表示第i个登山队攀爬的区段[Ai,Bi],其中0<=Ai<=Bi<=N。
Output
Q行,每行为一个整数,表示第i个登山队插旗的高度。
Sample Input
10
0
1
2
3
2
3
4
3
2
1
0
5
0 10
2 4
3 7
7 9
8 8
Sample Output
4
3
4
3
2
看了很多大佬的介绍,ST表其实就是DP思想。
a[i][j]=a[这个位置的下标][包括往后的2^j个数];\
1.输入
{
a[i][0]//从i开始的第一个数就是自己
}
2.处理数据
{
for(rr int j = 1;(1<<j) <= n;++j) //st表初始化,j是长度
{
for(rr int i = 0; i + (1<<j)-1 <=n;++i)
/*
i是头头。
ps:我交了几次90分就是没有把i从0开始滚orz,,
i要-1是因为i包含在j里了。
*/
a[i][j] = max(a[i][j-1],a[i+(1<<(j-1))][j-1]);
/*
从左边【i】_【j-1】和右边【i+2^(j-1)】_【j-1】 //
反正两边都有2^j那么多个数//
什么?你说为什么用j-1?
!o_o!
当然是因为我在算【i】【j】。
*/
}
}
3.回答
{
for(int i = 1; i<= m; i++)//共m条询问
{
scanf("%d%d",&x,&y);
if(!x&&!y)
puts("0");
k=int(log2(y-x+1));
/*
x~y一共有y-x+1个数,然后又是log级的,
暂时不知道为啥用Int向下取整,走过路过的大佬求指教。
*/
printf("%d\n",max(a[x][k],a[y-(1<<k)+1][k]));//记得【y-(1<<k)要加1】!
}
}