描述 Description
老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3…编号,然后不定时的问管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。
在询问过程中账本的内容可能会被修改
输入格式 Input Format
输入中第一行有两个数m,n表示有m(m<=100000)笔账,n表示有n个问题,n<=100000。
接下来每行为3个数字,第一个p为数字1或数字2,第二个数为x,第三个数为y
当p=1 则查询x,y区间
当p=2 则改变第x个数为y
输出格式 Output Format
输出文件中为每个问题的答案。具体查看样例。
样例输入 Sample Input
10 3
1 2 3 4 5 6 7 8 9 10
1 2 7
2 2 0
1 1 10
样例输出 Sample Output
2 0
时间限制 Time Limitation
各个测试点1s
解析:
线段树或者rmq可做。。。
本人用线段树实现,1操作就query(1,1,n,x,y),查询x-y区间。
2操作就update(1,1,n,x,y),把x变为y。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int inf=1000000000;
const int N=100000+10;
int minn[4*N];
int n,m,mi;
int a[N];
void readdata()
{
freopen("tyvj1038.in","r",stdin);
freopen("tyvj1038.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
}
void build(int p,int l,int r)
{
if(l==r){minn[p]=a[l];return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build((p<<1)+1,mid+1,r);
minn[p]=min(minn[p<<1],minn[(p<<1)+1]);
}
void update(int p,int l,int r,int x,int y)
{
if(l==r && r==x){minn[p]=y;return;}
int mid=(l+r)>>1;
if(x<=mid)update(p<<1,l,mid,x,y); else update((p<<1)+1,mid+1,r,x,y);
minn[p]=min(minn[p<<1],minn[(p<<1)+1]);
}
int query(int p,int ll,int rr,int l,int r)
{
if(l<=ll && rr<=r){return mi=minn[p];}
int mid=(ll+rr)>>1;
if(r<=mid) return query(p<<1,ll,mid,l,r);
else if(l>mid) return query((p<<1)+1,mid+1,rr,l,r);
else return min( query(p<<1,ll,mid,l,mid) , query((p<<1)+1,mid+1,rr,mid+1,r) );
}
void work()
{
int op,a,b;
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&op,&a,&b);
if(op==1)
printf("%d ",query(1,1,n,a,b));
else update(1,1,n,a,b);
}
}
int main()
{
readdata();
work();
return 0;
}