poj3264Balanced Lineup(倍增ST表)

Balanced Lineup

Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 52328   Accepted: 24551
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 ≤ A ≤ B ≤ N), 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
//先敲个板子
#include<iostream>
#include<cstdio>
#include<cstring>

#define maxn 1000000

using namespace std;
int n,m,ans,x,y,a[maxn],p[maxn];
int f1[maxn][25],f2[maxn][25];

inline int init()
{
    int x=0,f=1;char c=getchar();
    while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();}
    return x*f;
}

int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}

void ST()
{
    for(int i=1;i<=n;i++)
      f1[i][0]=f2[i][0]=a[i];
    for(int j=1;j<=20;j++)
      for(int i=1;i+(1<<j)-1<=n;i++)
        {
            f1[i][j]=min(f1[i][j-1],f1[i+(1<<j-1)][j-1]);
            f2[i][j]=max(f2[i][j-1],f2[i+(1<<j-1)][j-1]);
        }
    for(int i=1;i<=n;i++)
      for(int j=0;j<=20;j++)
           if((1<<j)>i)
           {
              p[i]=j-1;
              break;
        }
}

int query(int l,int r)
{
    int k=p[r-l+1];
    int ans1=min(f1[l][k],f1[r-(1<<k)+1][k]);
    int ans2=max(f2[l][k],f2[r-(1<<k)+1][k]);
    return ans2-ans1;
}

int main()
{
    n=init();m=init();
    for(int i=1;i<=n;i++)
      a[i]=init();
    ST();
    for(int i=1;i<=m;i++)
    {
        x=init();y=init();
        printf("%d\n",query(x,y));
    }
    return 0;
}
时间: 2024-11-02 15:40:49

poj3264Balanced Lineup(倍增ST表)的相关文章

poj 3264 倍增 ST表

#include<iostream> #include<cmath> using namespace std; const int maxn=1e5+10; int a[maxn]; int st[maxn][50]; int ST[maxn][50]; int quick(int a,int n) { int ans=1; while(n) { if(n&1) ans*=a; a=a*a; n>>1; } return ans; } int main() {

倍增思想到ST表RMQ

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 36864   Accepted: 17263 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 Joh

POJ 3264 Balanced Lineup ST表

链接:http://poj.org/problem?id=3264 题意:给一串数字,多次询问,求区间最大值和区间最小值的差. 思路:RMQ问题,可以用O(N^2)的预处理,然后每次O(1)的查询,可以用线段树,O(N)的建树,O(logN)的查询,可以用ST表记录,O(NlogN)的预处理,O(1)的查询. 实际上ST表的预处理过程也是一个DP的过程dp[i][j]表示从第i位开始连续2^j位的区间最值. 预处理:dp[i][j]=min(dp[i][j],dp[i+2^j][j]),查询:q

【倍增】RMQ的ST表算法

RMQ问题:给定一个长度为N的区间,M个询问,每次询问Li到Ri这段区间元素的最大值/最小值. RMQ的高级写法一般有两种,即为线段树和ST表. 本文主要讲解一下ST表的写法.(以区间最大值为例) ST表:一种利用dp求解区间最值的倍增算法. 定义:f[i][j]表示i到i+2^j-1这段区间的最大值. 预处理:f[i][0]=a[i].即i到i区间的最大值就是a[i]. 状态转移:将f[i][j]平均分成两段,一段为f[i][j-1],另一段为f[i+2^(j-1)][j-1]. 两段的长度均

hdu6107 倍增法st表

发现lca的倍增解法和st表差不多..原理都是一样的 /* 整篇文章分成两部分,中间没有图片的部分,中间有图片的部分 分别用ST表求f1,f2表示以第i个单词开始,连续1<<j行能写多少单词 */ #include<bits/stdc++.h> #define FIN freopen("in.txt","r",stdin); using namespace std; #define ll long long #define MX 100005

CF1190E Tokitsukaze and Explosion 二分、贪心、倍增、ST表

传送门 最小值最大考虑二分答案,不难发现当最小值\(mid\)确定之后,原点到所有直线的距离一定都是\(mid\)时才是最优的,也就是说这些直线一定都是\(x^2+y^2=mid^2\)的切线. 接下来考虑一个点会被哪些切线所保护.作出这个点到圆的公切线,得到两个切点,那么在这两个切点之间的优弧上选择一个点,以它为切点的切线就可以保护当前点.也就是说能够保护一个点的切线的切点在圆上表现为一段角度的区间.可以用解析几何计算出这个角度的区间. 接下来需要在\([-\pi , \pi]\)上选择不超过

51nod2621 树上距离一题四解ST表+倍增+Tarjan+树剖

LCA裸题 只有代码无原理,给自己复习用 1. ST表(这题2^10就够了) 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=2e3+50; 5 6 int cnt,dfn[maxn],dep[maxn],dp[maxn][21],lg2[maxn],dis[maxn],w[maxn][maxn]; 7 std::vector<int> G[maxn]; 8 void dfs(int u,in

[模板]ST表浅析

ST表,稀疏表,用于求解经典的RMQ问题.即区间最值问题. Problem: 给定n个数和q个询问,对于给定的每个询问有l,r,求区间[l,r]的最大值.. Solution: 主要思想是倍增和区间dp. 状态:dp[i][j] 为闭区间[i,i+2^j-1]的最值. 这个状态与转移方程的关系很大,即闭区间的范围涉及到了转移方程的简便性. 转移方程:dp[i][j]=max(dp[i][j-1],dp[i+2^(j-1)][j-1]). 这是显然的,但这里有个细节:第一个项的范围为[i,i+2^

说一说ST表 讲一讲水题

ST表 一.算法介绍 如何快速求解RMQ问题呢?暴力复杂度O(n),线段树复杂度O(n)~O(logn),要是数据规模达到10^7或者更高呢?我们需要一种可以做到O(1)查询的算法,这时就可以用到ST表. 我们用 f[i][j] 表示从 j 位置开始往右 2^i 个数内的最大值,用 g[i][j] 表示从j位置开始往左 2^i 个数内的最大值.所以 f[0][j] , g[0][j] 就为 j 位置上的数,可以在预处理中O(n)处理掉. 接下来我们要求出每个位置的每个 2^i 区间的最大值.可以