poj3264 rmq问题——st算法

来源:互联网 发布:比特币闪电网络 编辑:程序博客网 时间:2024/05/17 06:51
Balanced Lineup
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 27060 Accepted: 12697Case 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 andQ.
Lines 2..N+1: Line i+1 contains a single integer that is the height of cowi
Lines N+2..N+Q+1: Two integers A and B (1 ≤ABN), representing the range of cows fromA toB 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 31734251 54 62 2

Sample Output

630

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;} 


原创粉丝点击