JDFZOJ 2175 忠诚2 - 线段树
JDFZOJ 2175 忠诚2
题目链接:JDFZOJ 2175 忠诚2
算法标签: 线段树
题目
题目描述
老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记 \(k\) 次账,由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3…编号,然后不定时的问管家问题,问题是这样的:在 \(a\) 到 \(b\) 号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。
在询问过程中账本的内容可能会被修改
输入格式
输入中第一行有两个数 \(m,n\) 表示有 \(m(m\le100000)\) 笔账, \(n\) 表示有n个问题,\(n\le100000\)。
接下来每行为3个数字,第一个 \(p\) 为数字1或数字2,第二个数为 \(x\) ,第三个数为 \(y\)
当p=1 则查询x,y区间
当p=2 则改变第x个数为y
输出格式
输出文件中为每个问题的答案。具体查看样例。
输入输出样例
输入 #1
10 3
1 2 3 4 5 6 7 8 9 10
1 2 7
2 2 0
1 1 10
输出 #1
2 0
题解:
忠诚 传送门 ,的加强版,在原题查询的基础上加入了修改, 按照线段树的修改操作
void fix(int pos,int l,int r,int x,int y)
{
int mid=(l+r)>>1;
if(l==r) {f[pos]=y;return;}
if(x<=mid) fix(ls,l,mid,x,y);
else if(x>mid) fix(rs,mid+1,r,x,y);
f[pos]=min(f[ls],f[rs]);
}
值得注意的是,这里所传参数 \(x,y\) ,并非同查询一样是一个区间,而表示将 \(x\) 改为 \(y\).
其他的就是同忠诚的线段树做法一样,区间查询即可。
AC代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#define lson pos << 1
#define rson pos << 1 | 1
using namespace std;
const int maxn = 100010;
int n, m, a[maxn], tree[maxn << 2], ans[maxn], cnt;
void build(int pos, int l, int r)
{
int mid = (l + r) >> 1;
if (l == r)
{
tree[pos] = a[l];
return ;
}
build(lson, l, mid);
build(rson, mid + 1, r);
tree[pos] = min(tree[lson], tree[rson]);
}
void fix(int pos, int l, int r, int x, int y)
{
int mid = (l + r) >> 1;
if (l == r)
{
tree[pos] = y;
return ;
}
if (x <= mid) fix(lson, l, mid, x, y);
else if (x > mid) fix(rson, mid + 1, r, x, y);
tree[pos] = min(tree[lson], tree[rson]);
}
int query(int pos, int l, int r, int x, int y)
{
int res=1 << 30;
int mid = (l + r) >> 1;
if(x <= l && r <= y) return tree[pos];
if(y <= mid)
res = min(res, query(lson, l, mid, x, y));
else if(x > mid)
res = min(res, query(rson, mid + 1, r, x, y));
else
{
int rea = query(lson, l, mid, x, y);
int reb = query(rson, mid + 1, r, x, y);
res = min(res, min(rea, reb));
}
return res;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
cin >> a[i] ;
build(1, 1, n);
for (int i = 1; i <= m; i ++ )
{
int a, b, c;
cin >> a >> b >> c;
if (a == 1)
ans[++cnt] = query(1, 1, n, b, c);
else
fix(1, 1, n, b, c);
}
if (cnt >= 1) cout << ans[1];
for (int i = 2; i <= cnt; i ++ )
{
cout << ' ' << ans[i];
}
return 0;
}