poweroj(2376线段树区间最值求和)

来源:互联网 发布:电子书包的软件 编辑:程序博客网 时间:2024/04/30 06:47
给出一个含有 N 个元素的序列,即 a[1], a[2], a[3], a[4],,,,,a[n],,,
然后有 Q 次询问,每次询问都是输入[le, ri],
需要求出这个区间中的最小值、最大值、以及这个区间的元素的和。
Input

多组输入。
第一行输入N, Q,意思同上 (1 <= N <= 100000, 1 <= Q <= 100000)
第二行输入 N 个 整数 ,即a[i] ( 0 <= a[i] <= 10000)
然后接下来的 Q 行,每行输入 le, ri ( 1 <= le <= ri <= N )
Output

对于每次询问,输出区间中的最小值、最大值、区间和(相邻数字之间有一个空格)。
Sample Input
Raw
4 10
4 8 6 1
1 1
1 2
1 3
1 4
2 2
2 3
2 4
3 3
3 4
4 4
Sample Output
Raw
4 4 4
4 8 12
4 8 18
1 8 19
8 8 8
6 8 14
1 8 15
6 6 6
1 6 7
1 1 1
代码:
#include <string.h>
#include <algorithm>
#include <stdio.h>
#define MAXN 100010
#define inf 0x3f3f3f3f
using namespace std;
struct node{
int l,r;//区间[l,r]
int add;//区间的延时标记
int sum;//区间和
int mx; //区间最大值
int mn; //区间最小值
}tree[MAXN<<2];//一定要开到4倍多的空间

void pushup(int 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);
}
void pushdown(int 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;

}
}
void build(int l,int r,int index){
tree[index].l = l;
tree[index].r = r;
tree[index].add = 0;//刚开始一定要清0
if(l == r){
scanf("%d",&tree[index].sum);
tree[index].mn = tree[index].mx = tree[index].sum;
return ;
}
int mid = (l+r)>>1;
build(l,mid,index<<1);
build(mid+1,r,index<<1|1);
pushup(index);
}
int query1(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].mn;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
Min = min(query1(l,r,index<<1),Min);
}
if(r > mid){
Min = min(query1(l,r,index<<1|1),Min);
}
return Min;
}
int query2(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].mx;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
Max = max(query2(l,r,index<<1),Max);
}
if(r > mid){
Max = max(query2(l,r,index<<1|1),Max);
}
return Max;
}
int query3(int l,int r,int index){
if(l <= tree[index].l && r >= tree[index].r){
return tree[index].sum;
}
pushdown(index);
int mid = (tree[index].l+tree[index].r)>>1;
int ans = 0;
int Max = 0;
int Min = inf;
if(l <= mid){
ans += query3(l,r,index<<1);
}
if(r > mid){
ans += query3(l,r,index<<1|1);
}
return ans;
}
int main()
{
int n,m;
int A,B;
while(scanf("%d%d",&n,&m)!=EOF)
{
build(1,n,1);
for(int i=0;i<m;i++)
{
scanf("%d%d",&A,&B);
int x,y,z;
x=query1(A,B,1);
y=query2(A,B,1);
z=query3(A,B,1);
printf("%d",x);
printf(" %d %d\n",y,z);

}
}
return 0;
}

0 0
原创粉丝点击