COGS182. [USACO Jan07] 均衡队形

题目描述
农夫约翰的 N (1 ≤ N ≤ 50,000)头奶牛,每天挤奶时总会按同样的顺序站好。一日,农夫约翰决定为奶牛们举行一个“终极飞盘”比赛。为简化问题,他将从奶牛队列中选出一个连续区间来进行游戏。不过,参加游戏的奶牛要玩的开心的话就不能在身高上差距太大。农夫约翰制定了 Q (1 ≤ Q ≤ 200,000) 个预定的参赛组,给出它们的身高 (1 ≤ 身高 ≤ 1,000,000)。对每个参赛组,他需要你帮助确定组中最高牛和最低牛的身高差。
输入格式
第 1 行: 两个空格隔开的整数,N 和 Q。
第 2..N+1 行: 第 i+1 行包含一个整数表示第 i 头牛的身高。
第 N+2..N+Q+1 行: 两个整数 A 和 B(1 ≤ A ≤ B ≤ N),表示一个从 A 到 B 的参赛组区间。
输出格式
第 1..Q 行: 每行包含一个整数来表示区间上最大身高差。
样例输入
6 3
1
7
3
4
2
5
1 5
4 6
2 2
样例输出
6
3
0

为了训练一下线段树而写的模板题。
教训:一定要算好内存,开数组要记得两倍!!(一开始数组开小导致爆了)

#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXX 1100000
using namespace std;
int a[51000];
int n,m;
struct data{
    int ma,mi;
}num[1100000];
void read(int &x)
{
    char t=getchar();x=0;int f=1;
    while((t<48)or(t>57)){if(t=='-')f=-1;t=getchar();}
    while((t>=48)and(t<=57)){x=x*10+t-48;t=getchar();}
    x*=f;
}
void updata(int now)
{
    num[now].ma=max(num[now<<1].ma,num[(now<<1)+1].ma);
    num[now].mi=min(num[now<<1].mi,num[(now<<1)+1].mi);
}
void build(int now,int l,int r)
{
    if (l==r)
    {
        num[now].ma=a[l];
        num[now].mi=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(now<<1,l,mid);
    build((now<<1)+1,mid+1,r);
    updata(now);
}
data query(int now,int l,int r,int lrange,int rrange)
{
    data t;
    if ((lrange<=l)and(r<=rrange))
    {
        t.ma=num[now].ma;
        t.mi=num[now].mi;
        return t;
    }
    int mid=(l+r)>>1;
    data t1,t2;
    if (lrange<=mid) t1=query(now<<1,l,mid,lrange,rrange);
    else t1.ma=0,t1.mi=MAXX;
    if (mid<rrange) t2=query((now<<1)+1,mid+1,r,lrange,rrange);
    else t2.ma=0,t2.mi=MAXX;
    t.ma=max(t1.ma,t2.ma);
    t.mi=min(t1.mi,t2.mi);
    return t;
}
int main()
{
    freopen("lineup.in","r",stdin);
    freopen("lineup.out","w",stdout);
    read(n),read(m);
    for (int i=1;i<=n;++i) read(a[i]);
    build(1,1,n);
    for (int i=1;i<=m;++i)
    {
        int x,y;
        read(x),read(y);
        data ans=query(1,1,n,x,y);
        printf("%d\n",ans.ma-ans.mi);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值