时间限制:1000 ms | 内存限制:65535 KB
难度:2
描述
给出N个整数,执行M次询问。
对于每次询问,首先输入三个整数C、L、R:
如果C等于1,输出第L个数到第R个数之间的最小值;
如果C等于2,输出第L个数到第R个数之间的最大值;
如果C等于3,输出第L个数到第R个数之间的最小值与最大值的和。
(包括第L个数和第R个数)。
输入
首先输入一个整数T(T≤100),表示有T组数据。
对于每组数据,先输入一个整数N(1≤N≤10000),表示有N个整数;
接下来一行有N个整数a(1≤a≤10000);
然后输入一个整数M,表示有M次询问;
接下来有M行(1≤M≤10000),每行有3个整数C、L、R(1≤C≤3,1≤L≤R≤N)。
输出
按照题意描述输出。每个输出占一行。
样例输入
2
4
1 3 2 4
2
1 1 4
2 2 3
5
1 2 3 4 5
1
3 1 5
样例输出
1
3
6
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<iomanip>
using namespace std;
typedef int _____I;
const int N=1e6+10;
const int INF=0x3f3f3f3f;
#define ERX(___I,__I,_I) for(_____I ___I = __I;___I < _I; ___I++)
#define ERD(___I,__I,_I) for(_____I ___I = __I;___I <= _I; ___I++)
#define RED(___I,__I,_I) for(_____I ___I = __I;___I >= _I; ___I--)
超时代码
/*
int t;
int n,m;
int c,l,r;
int a[10200];
int main(){
// ios::sync_with_stdio(false);
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) cin>>a[i];
scanf("%d",&m);
int x,y,z;
for(int i=0;i<m;i++){
scanf("%d%d%d",&x,&y,&z);
if(x==1){
int minn=INF;
for(int j=y;j<=z;j++)
if(minn>a[j]) minn=a[j];
printf("%d\n",minn);
}
else if(x==2){
int maxx=0;
for(int j=y;j<=z;j++)
if(maxx<a[j]) maxx=a[j];
printf("%d\n",maxx);
}
else {
int maxx=0,minn=INF;
for(int j=y;j<=z;j++){
if(maxx<a[j]) maxx=a[j];
if(minn>a[j]) minn=a[j];
}
printf("%d\n",maxx+minn);
}
}
}
return 0;
}
*/
#include<stdio.h>
int p[10000+10];
struct record{
int left,right,max,min;
}num[100000+10];
int MAX(int x,int y){return x>y?x:y;}
int MIN(int x,int y){return x<y?x:y;}
int buildmin(int left,int right,int node){ //从节点1 赋值为整个区间 然后以此分两半给其左右子树
int mid;
num[node].left=left; //对该节点 进行左右区间的赋值
num[node].right=right;
if(left==right) return num[node].min=p[left]; //如果说该区间的 叶子节点 最后的叶子节点 分布为 1-n 因此该语句会执行n次
mid=(left+right)>>1; //进行左右子树的 遍历
return num[node].min=MIN(buildmin(left,mid,node*2),buildmin(mid+1,right,node*2+1)); //返回 将节点的最小值取 下一个 mid的 左区间到 mid 节点为 node*2 右区间为 mid+1 到 right 节点为 node*2+1
}
int buildmax(int left,int right,int node){ //每一个区间的最大值 赋值给了该区间
int mid;
num[node].left=left;
num[node].right=right;
if(left==right) return num[node].max=p[left]; //如果说到了 叶子节点 就将该节点的 最大值给 该数组
mid=(left+right)>>1;//除2
return num[node].max=MAX(buildmax(left,mid,node*2),buildmax(mid+1,right,node*2+1));
}
int querymin(int left,int right,int node){//求最小值
int mid;
if(num[node].left==left&&num[node].right==right) return num[node].min; //如果二分的找到了该区间 就将该区间的最小值 返回
mid=(num[node].left+num[node].right)>>1; //该节点的左右区间 二分向下
if(right<=mid) return querymin(left,right,node*2);// 如果要找到的区间的 左端 小于等于 二分出来的mid的话 就进行原本区间的递归查询
else{ //否则right 大于 mid 的话 就进行 判断
if(left>mid) return querymin(left,right,node*2+1); //如果left大于mid 就进行 原本区间的递归
else return MIN(querymin(left,mid,node*2),querymin(mid+1,right,node*2+1));//除了上面两种情况 就剩该情况了
}
}
//1.______left_____right___mid_____________________________ querymin(left,right,node*2); 基于准确区间的查询
//2._______________________mid___left_______right__________ querymin(left,right,node*2+1); 同上
//3._____________left______mid______right__________________ MIN(querymin(left,mid,node*2),querymin(mid+1,right,node*2+1)); 基于两个区间的 查询 最后只用返回一个 两中情况的最优
int querymax(int left,int right,int node){//求最大值
int mid;
if(num[node].left==left&&num[node].right==right)return num[node].max;
mid=(num[node].left+num[node].right)>>1;
if(right<=mid) return querymax(left,right,node*2);
else{
if(left>mid) return querymax(left,right,node*2+1);
else return MAX(querymax(left,mid,node*2),querymax(mid+1,right,node*2+1));
}
}
int main(){
int t,n,m,i,j;
int a,b,c;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&p[i]);
buildmin(1,n,1); //建树
buildmax(1,n,1); //建树
//得到每个区间的 最大 最小值
scanf("%d",&m);//输入m个数据
while(m--){
scanf("%d%d%d",&a,&b,&c); //输入 操作数
if(a==1) printf("%d\n",querymin(b,c,1)); //得到最小的 值 从 b到c区间 从节点为一的
if(a==2) printf("%d\n",querymax(b,c,1)); //返回最大值 在 b c 区间的
if(a==3) printf("%d\n",querymin(b,c,1)+querymax(b,c,1));
}
}
return 0;
}
/*
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#include <fstream>
#include <limits>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cassert>
using namespace std;
struct la{
int w;
int z;
}a[10000+10];
bool cmp(la x,la y){return x.z<y.z;}
int main(){
int t,T,i,j,k,n,c,l,r;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i].z);
a[i].w=i;
}
sort(a+1,a+n+1,cmp);
scanf("%d",&T);
while(T--){
scanf("%d %d %d",&c,&l,&r);
int da=0;
if(c==1||c==3)
for(i=1;i<=n;i++){
if(a[i].w<=r&&a[i].w>=l){
da+=a[i].z;
break;
}
}
if(c==2||c==3)
for(i=n;i>=1;i--){
if(a[i].w<=r&&a[i].w>=l){
da+=a[i].z;
break;
}
}
printf("%d\n",da);
}
}
return 0;
}*/