1174 区间中最大的数
基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:
给出一个有N个数的序列,编号0 - N - 1。进行Q次查询,查询编号i至j的所有数中,最大的数是多少。
例如: 1 7 6 3 1。i = 1, j = 3,对应的数为7 6 3,最大的数为7。(该问题也被称为RMQ问题)
Input
第1行:1个数N,表示序列的长度。(2 <= N <= 10000)
第2 - N + 1行:每行1个数,对应序列中的元素。(0 <= S[i] <= 10^9)
第N + 2行:1个数Q,表示查询的数量。(2 <= Q <= 10000)
第N + 3 - N + Q + 2行:每行2个数,对应查询的起始编号i和结束编号j。(0 <= i <= j <= N - 1)
Output
共Q行,对应每一个查询区间的最大值。
Input示例
5
1
7
6
3
1
3
0 1
1 3
3 4
Output示例
7
7
3
思路:用了自己常用的一个线段树模板
代码:
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <queue>
// #define MAXN 100010
// #define inf 10000000000000000
using namespace std;
typedef long long LL;
struct node{
LL l,r;//区间[l,r]
LL add;//区间的延时标记
LL sum;//区间和
LL mx; //区间最大值
LL mn; //区间最小值
LL pm;//历史最小值
}tree[800001];//一定要开到4倍多的空间
void pushup(LL index){
tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
tree[index].pm = min(tree[index<<1].pm,tree[index<<1|1].pm);
}
void pushdown(LL index){
//说明该区间之前更新过
//要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新
if(tree[index].add != 0){
//替换原来的值
/*
tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].mx = tree[index].add;
tree[index<<1|1].mx = tree[index].add;
tree[index<<1].mn = tree[index].add;
tree[index<<1|1].mn = tree[index].add;
tree[index<<1].add = tree[index].add;
tree[index<<1|1].add = tree[index].add;
tree[index].add = 0;*/
//在原来的值的基础上加上val
tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].mx += tree[index].add;
tree[index<<1|1].mx += tree[index].add;
tree[index<<1].mn += tree[index].add;
tree[index<<1].pm = min(tree[index<<1].mn, tree[index<<1].pm);
tree[index<<1|1].mn += tree[index].add;
tree[index<<1|1].pm = min(tree[index<<1|1].mn, tree[index<<1|1].pm);
tree[index<<1].add += tree[index].add;
tree[index<<1|1].add += tree[index].add;
tree[index].add = 0;
}
}
void build(LL l,LL r,LL index){
tree[index].l = l;
tree[index].r = r;
tree[index].add = 0;//刚开始一定要清0
if(l == r){
scanf("%d",&tree[index].sum);
tree[index].pm=tree[index].mn = tree[index].mx = tree[index].sum;
return ;
}
LL mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
void updata(LL l,LL r,LL index,LL val){
if(l <= tree[index].l && r >= tree[index].r){
/*把原来的值替换成val,因为该区间有tree[index].r-tree[index].l+1
个数,所以区间和 以及 最值为:
*/
/*tree[index].sum = (tree[index].r-tree[index].l+1)*val;
tree[index].mn = val;
tree[index].mx = val;
tree[index].add = val;//延时标记*/
//在原来的值的基础上加上val,因为该区间有tree[index].r-tree[index].l+1
//个数,所以区间和 以及 最值为:
tree[index].sum += (tree[index].r-tree[index].l+1)*val;
tree[index].mn += val;
tree[index].pm = min(tree[index].mn,tree[index].pm);
tree[index].mx += val;
tree[index].add += val;//延时标记
return ;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
if(l <= mid){
updata(l,r,index<<1,val);
}
if(r > mid){
updata(l,r,index<<1|1,val);
}
pushup(index);
}
LL query(LL l,LL r,LL index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].mx;
//return tree[index].pm;
//return tree[index].mn;
}
pushdown(index);
LL mid = (tree[index].l+tree[index].r)>>1;
LL ans = 0;
LL Max = 0;
LL Min = 1e18;
if(l <= mid){
// ans += query(l,r,index<<1);
Max = max(query(l,r,index<<1),Max);
// Min = min(query(l,r,index<<1),Min);
}
if(r > mid){
// ans += query(l,r,index<<1|1);
Max = max(query(l,r,index<<1|1),Max);
// Min = min(query(l,r,index<<1|1),Min);
}
//return ans;
return Max;
//return Min;
}
int main()
{
int n,m;int q,x,y,z;
//cin>>n;
scanf("%d",&n);
build(1,n,1);
scanf("%d",&m);
//in>>m;
while(m--){
scanf("%d%d",&x,&y);
// scanf("%d%d%d",&x,&y,&z);
// updata(x,y,1,z);
//printf("%I64d\n",query(x,y,1));
printf("%lld\n",query(x+1,y+1,1));
//cout<<query(x,y,1)<<endl;
// for(int i = 1; i <= n; ++i){
// printf("a[%d] = %d\n",i,query(i,i,1));
// }
}
return 0;
}