忠诚
题目描述
老管家是一个聪明能干的人。他为财主工作了整整 10 年,财主为了让自已账目更加清楚。要求管家每天记 k 次账,由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按 1,2,3… 编号,然后不定时的问管家问题,问题是这样的:在 a 到 b 号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。
在询问过程中账本的内容可能会被修改
输入
输入中第一行有两个数 m;n 表示有 m(m≤100000) 笔账 ,n 表示有 n 个问题,n≤100000。
接下来每行为 3 个数字,第一个 p 为数字 1 或数字 2,第二个数为 x,第三个数为 y。
当 p=1 则查询 x;y 区间
当 p=2 则改变第 x 个数为 y
输出
输出文件中为每个问题的答案。具体查看样例。
样例
in
10 3
1 2 3 4 5 6 7 8 9 10
1 2 7
2 2 0
1 1 10
out
2 0
解法
此题是线段树模板题,创建修改单点和查询区间函数即可
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,sum[400010],a[400010];
int p(int x){
sum[x] = min(sum[x*2],sum[x*2+1]);
}
// 初始化函数
void b(int l,int r,int rt){
if(l==r){
sum[rt] = a[l];return ;
}
int mid = l+r>>1;
b(l,mid,rt*2);
b(mid+1,r,rt*2+1);
p(rt);
}
// 修改函数
void xx(int l,int r,int rt,int x,int d){
if(l==r){
sum[rt] = d;
return ;
}
int mid = l+r>>1;
if( x<=mid) xx(l,mid,rt*2,x,d);
else xx(mid+1,r,rt*2+1,x,d);
p(rt);
}
// 查询区间
int c(int l,int r,int rt,int x,int y){
if(l>=x and y>=r){
return sum[rt];
}
int mid = l+r>>1;
int ans=1234567890;
if(x<=mid){
ans = min(ans,c(l,mid,rt*2,x,y));
}
if(y>mid){
ans = min(ans,c(mid+1,r,rt*2+1,x,y));
}
return ans;
}
int main(){
cin >> n >> m; // 输入
for(int i=1;i<=n;i++){
cin >> a[i];
}
b(1,n,1); // 初始化
for(int i=1;i<=m;i++){ // 遍历每一个问题
int p,x,y;
cin >> p >> x >> y;
if(p==1){
cout << c(1,n,1,x,y) << ' ';
}else{
xx(1,n,1,x,y);
}
}
return 0;
}
感谢观看
这个是我和朋友创建的域欢迎加入!