差距(模板题)

差距 (difi)
【题目描述】
给定一个 N 个数的数列,再给出 Q 个询问 A B,询问 A 到 B 之间最大值和最
小值的差。
【输入文件】
第一行两个整数 N,Q。
接下来一行 N 个整数表示 Ai。
接下来 Q 行,表示一个询问 A B。
【输出文件】
Q 行,每行对应一个询问的答案。
【样例输入】
5 4
7 2 4 3 8
2 4
2 5
1 3
3 5
【样例输出】
2 6 5 5
【数据规模】
对于 100%的数据 N<=200000, Q<=100000

这道题就是一道模板题,介绍两种打法

(1):线段树

裸的线段树区间查询,这里要开两个线段树,一个记录较大的节点,一个记录较小的节点。(只要改动up即可,较大的节点就在up时取max)。

#include<bits/stdc++.h>
#define maxn 100007
using namespace std;
int i,j,k,n,m,q,tot,lf,rf,mid;
int f[maxn],add[maxn<<2],sum[maxn<<2],sum1[maxn<<2];
int minn(int a,int b){return a<b?a:b;}
int maxx(int a,int b){return a>b?a:b;}
void up(int node){sum[node]=minn(sum[node<<1],sum[(node<<1)+1]);}
void up1(int node){sum1[node]=maxx(sum1[node<<1],sum1[(node<<1)+1]);}
void build(int node,int l,int r){
    if(l==r){
        sum[node]=f[l];
        sum1[node]=f[l];
        return;
    }
    int mid=(l+r)>>1;
    build(node<<1,l,mid);
    build((node<<1)+1,mid+1,r);
    up(node);up1(node);
}
long long query(int l,int r,int le,int ri,int node){
    if(le<=l&&r<=ri){
        return sum[node];
    }
    long long ans=2147483647;
    int mid=(l+r)>>1;
    if(le<=mid) ans=minn(query(l,mid,le,ri,node<<1),ans);
    if(ri>=mid+1) ans=minn(ans,query(mid+1,r,le,ri,(node<<1)+1));
    return ans;
}
long long query1(int l,int r,int le,int ri,int node){
    if(le<=l&&r<=ri){
        return sum1[node];
    }
    long long ans=-2147483647;
    int mid=(l+r)>>1;
    if(le<=mid) ans=maxx(query1(l,mid,le,ri,node<<1),ans);
    if(ri>=mid+1) ans=maxx(ans,query1(mid+1,r,le,ri,(node<<1)+1));
    return ans;
}
int read(){
    char c;while(c=getchar(),(c<'0'||c>'9')&&c!='-');int x=0,y=1;
    if(c=='-') y=-1;else x=c-'0';while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';
    return x*y;
}
int main()
{
    n=read(),q=read();
    for(int i=1;i<=n;i++) f[i]=read();
    build(1,1,n);
    for(int i=1;i<=q;i++){
        int x=read(),y=read();
        printf("%lld\n",query1(1,n,x,y,1)-query(1,n,x,y,1));
    }
    return 0;
}

(2)RMQ

RMQ更不用说了,直接暴力查询区间最大值,最小值

#include<cstdio>
#include<cstdlib>
using namespace std;
int i,j,k,n,m,tot,ans,q;
int d[100005][20],f[100005],p[100005][20];
int read(){
    char c;while(c=getchar(),(c<'0'||c>'9')&&c!='-');int x=0,y=1;
    if(c=='-') y=-1;else x=c-'0';while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';
    return x*y;
}
int maxx(int a,int b){return a>b?a:b;}
int minn(int a,int b){return a<b?a:b;}
void rmq(int n){
    for(int i=1;i<=n;i++) d[i][0]=f[i];
    for(int j=1;(1<<j)<=n;j++)
     for(int i=1;i+(1<<j)-1<=n;i++)
     d[i][j]=maxx(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
long long query(int l,int r){
    int k=0;
    while((1<<k+1)<=r-l+1) k++;
    return maxx(d[l][k],d[r-(1<<k)+1][k]);
}
void rmq1(int n){
    for(int i=1;i<=n;i++) p[i][0]=f[i];
    for(int j=1;(1<<j)<=n;j++)
     for(int i=1;i+(1<<j)-1<=n;i++)
     p[i][j]=minn(p[i][j-1],p[i+(1<<(j-1))][j-1]);
}
long long query1(int l,int r){
    int k=0;
    while((1<<k+1)<=r-l+1) k++;
    return minn(p[l][k],p[r-(1<<k)+1][k]);
}
int main()
{
    n=read();q=read();
    for(int i=1;i<=n;i++) f[i]=read();
    rmq(n);rmq1(n);
    for(int i=1;i<=q;i++){
        int x=read(),y=read();
        printf("%lld\n",query(x,y)-query1(x,y));
    }
    return 0;
}
posted @ 2017-08-09 15:16  stevensonson  阅读(116)  评论(0编辑  收藏  举报