Balanced Lineup


Time Limit: 5000MS

 

Memory Limit: 65536K

Total Submissions: 27060

 

Accepted: 12697

Case Time Limit: 2000MS


Description


For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from the milking lineup to play the game. However, for all the cows to have fun they should not differ too much in height.

Farmer John has made a list of Q (1 ≤ Q ≤ 200,000) potential groups of cows and their heights (1 ≤height ≤ 1,000,000). For each group, he wants your help to determine the difference in height between the shortest and the tallest cow in the group.


Input


Line 1: Two space-separated integers, N and Q.
Lines 2.. N+1: Line i+1 contains a single integer that is the height of cow i
Lines N+2.. N+ Q+1: Two integers A and B (1 ≤ ABN), representing the range of cows from A to B inclusive.


Output


Lines 1.. Q: Each line contains a single integer that is a response to a reply and indicates the difference in height between the tallest and shortest cow in the range.


Sample Input


6 3 1 7 3 4 2 5 1 5 4 6 2 2


Sample Output


6 3 0


Source


​USACO 2007 January Silver​​​
解法:
可以用线段树做,也可以用st算法解决。
st算法解决区间最大最小值,预处理是nlogn的(同线段树),但查询却是o(1)。
st算法我就不讲了,这里推荐两篇个人认为讲的很好blog:
​​​http://kmplayer.iteye.com/blog/575725​​​
​​​http://blog.pfan.cn/cruxd/32510.html​​​(这里面说st就是一个打表算法,感觉新颖奇特,给人很多灵感。)
在下面贴出我的代码,个人认为已经是最快最简洁的了,但是在poj上却跑了2488ms,比第一名慢了近十倍,希望有路过的大牛指点一下我的程序慢在哪里,或分享一下更高效的算法,不甚感激!!!!!!
代码:

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cmath>
#define maxn (50000+10)
using namespace std;

int d[17]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};
int dmin[maxn][17],dmax[maxn][17];

void init()
{
freopen("poj3264.in","r",stdin);
freopen("poj3264.out","w",stdout);
}

inline int getin()
{
int ans=0;char tmp;
do tmp=getchar();
while(!isdigit(tmp));
do ans=(ans<<3)+(ans<<1)+tmp-'0';
while(isdigit(tmp=getchar()));
return ans;
}

void work()
{
int n=getin(),q=getin(),i,j;
for(i=1;i<=n;i++)dmin[i][0]=dmax[i][0]=getin();

for(j=1;d[j]<=n;j++)
for(i=1;i+d[j]-1<=n;i++)
{
dmax[i][j]=max(dmax[i][j-1],dmax[i+d[j-1]][j-1]);
dmin[i][j]=min(dmin[i][j-1],dmin[i+d[j-1]][j-1]);
}

int a,b,kmax,kmin;
for(i=1;i<=q;i++)
{
a=getin(),b=getin();
j=(int)(log((b-a+1)*1.0)/log(2.0));
kmax=max(dmax[a][j],dmax[b-d[j]+1][j]);
kmin=min(dmin[a][j],dmin[b-d[j]+1][j]);
printf("%d\n",kmax-kmin);
}
}

int main()
{
init();
work();
return 0;
}