差距(模板题)
差距 (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;
}