【POJ 3264】Balanced Lineup(RMQ算法||线段树)

来源:互联网 发布:网络管理零基础知乎 编辑:程序博客网 时间:2024/05/29 17:40

Balanced Lineup


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

题意:

一句话概括->求出给定区间内最大值与最小值的差值

思路:

此题可用两种方法写。1.线段树;2.新操作->RMQ算法
什么是RMQ?

Range Minimum/Maximum Query,对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。

可以看出这道题就是一道RMQ算法的裸题。
第一次见到RMQ算法,其实它(的预处理)就是个DP的思想,关键在于状态转移方程的理解。上那篇文章讲的很好可以看看。

代码:

RMQ算法版本
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int maxsum[200001][20],minsum[200001][20];int n,q;void Init(){    int i,j,lg=floor(log10(double(n))/log10(double(2)));    for(j=1;j<=lg;j++)        for(i=1;i<=n;i++)            if(i+(1<<j)-1<=n)            {                maxsum[i][j]=max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);                minsum[i][j]=min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);            }}int main(){    int k,a,b,lg;      scanf("%d %d", &n, &q);      for (int i = 1; i <= n; ++i){          scanf("%d", &k);          maxsum[i][0] = minsum[i][0] = k;      }      Init();      while(q--){          scanf("%d%d", &a, &b);          if (a > b) swap(a, b);          lg = floor(log10(double(b-a+1))/log10(double(2)));          //max(fmax[a][lg], fmax[b-(1<<lg)+1][lg]),两个区间中间有重叠,因此两者中较大的就是该区间的最大值          printf("%d\n", max(maxsum[a][lg], maxsum[b-(1<<lg)+1][lg])-min(minsum[a][lg], minsum[b-(1<<lg)+1][lg]));      }      return 0;   } 
线段树版本
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define MAX 200005#define INF 0xffffffusing namespace std;struct Tree{    int left;    int right;    int min;    int max;}tree[MAX<<2];//一般都是4倍int maxv,minv;void Build(int l,int r,int i){    tree[i].left=l;    tree[i].right=r;    tree[i].max=-INF;    tree[i].min=INF;    if(l==r) return ;    int mid=(l+r)/2;    {        Build(l,mid,i*2+1);        Build(mid+1,r,i*2+2);    }}void Insert(int i,int x,int val){    if(tree[i].left==tree[i].right)    {        tree[i].max=tree[i].min=val;        return ;    }        //递归更新最大最小值    tree[i].max=max(tree[i].max,val);    tree[i].min=min(tree[i].min,val);    int mid=(tree[i].left+tree[i].right)/2;    if(x<mid) Insert(i*2+1,x,val);    else Insert(i*2+2,x,val);}void Query(int l,int r,int i){    if(l<tree[i].left||r>tree[i].right) return ;    if(l==tree[i].left&&r==tree[i].right)    {        maxv=max(tree[i].max,maxv);        minv=min(tree[i].min,minv);        return ;    }    int mid=(tree[i].left+tree[i].right)/2;    if(l>mid) Query(l,r,i*2+2);    else if(r<=mid) Query(l,r,i*2+1);    else {        Query(l,mid,i*2+1);        Query(mid+1,r,i*2+2);    }}int main(){    int n,q,val;    scanf("%d %d",&n,&q);    Build(1,n,0); //这里用下标从0开始,下面也是(从1开始不知道为何WA了)    for(int i=0;i<n;i++)    {        scanf("%d",&val);        Insert(0,i,val);    }    while(q--)    {        int a,b;        maxv=-INF,minv=INF;//每次都初始化一下maxv,minv        scanf("%d %d",&a,&b);        Query(a,b,0);        printf("%d\n",maxv-minv);    }    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买房的合同丢了怎么办 押金的收据丢了怎么办 房东的合同掉了怎么办 个人档案里单位没有放合同怎么办 签的合同掉了怎么办 一方合同弄丢了怎么办 合同丢了怎么办如何补 签了定金合同对方违约怎么办 医学出生证明丢了怎么办 易通行出站未刷怎么办 炭烧酸奶过期了怎么办 西安建行etc坏了怎么办 电机在设备壳体中拔不出来怎么办 公司变更股东不能亲临现场怎么办? 公司股东变更老股东不签字怎么办 公司变更地址股东不签字怎么办 公司变更股份股东不签字怎么办 公司股东离职股东没变更过来怎么办 河南省宋基投资公司欠钱怎么办 曲江楼观2O18怎么办 华旭金卡身份证扫描不了怎么办 水表里有钱没水怎么办? ff14过图速度慢怎么办 想让电表跑的慢怎么办 家里电表突然没有电了怎么办 电表不识别电卡怎么办 家里水表不转了怎么办 车管所体检色弱怎么办 煤气押金单没了怎么办 中国建设银行登录密码忘了怎么办 中国建设银行登录密码忘记了怎么办 公司车辆怎么办换新能源牌 杭州新能源汽车牌照外地人怎么办 建行登录密码忘了怎么办 新捷达epc灯亮怎么办 捷达车玻璃升降偏离怎么办 交金中断一个月怎么办 博士拟录取没导师怎么办 保研联系导师后怎么办 特别害怕和导师交流怎么办 面试工资要少了怎么办