hiho #1077 : RMQ问题再临-线段树

线段树练手题,单点修改,区间查询,写个分块试试,分块下标用0-n-1比较好写

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1e6+5;
const int maxm=1e3+5;
int n,val[maxn],ans[maxm],l[maxm],r[maxm],belong[maxn],block,cnt;

void update(int q,int v){
    int blto=belong[q];
    int ff=0;
    if(ans[blto]>v)ans[blto]=val[q]=v;
    else if(ans[blto]==val[q]){
	val[q]=v;ans[blto]=INT_MAX;
	rep(i,l[blto],r[blto])ans[blto]=min(ans[blto],val[i]);
    }
    else {
       val[q]=v;
       if(block==1)ans[blto]=v;
    }
}

int q(int ql,int qr){
    int blto=belong[ql];
    if(l[blto]==ql&&qr==r[blto])return ans[blto];
    int res=INT_MAX;
    rep(i,ql,qr)res=min(res,val[i]);
    return res;
}

int query(int ql,int qr){
    int b1=belong[ql],b2=belong[qr];
    if(b1==b2)return q(ql,qr);
    else {
	int res=q(ql,r[b1]);
	b1++;
	while(b1<b2)res=min(res,ans[b1]),b1++;
	res=min(res,q(l[b2],qr));
	return res;
    }
}

void init(){
    block=sqrt(n);cnt=n/block;
    rep(i,1,cnt)
      l[i]=(i-1)*block+1,r[i]=i*block;
    if(n%block){
	l[cnt+1]=cnt*block+1;
	r[cnt+1]=n;
	cnt++;
    }
    rep(i,1,cnt)ans[i]=INT_MAX;
    rep(i,1,n){
	int p=i/block;
	if(i%block!=0)p++;
	belong[i]=p;
	ans[p]=min(ans[p],val[i]);
    }
}

int main(){
    int q,o,ql,qr;
    scanf("%d",&n);
    rep(i,1,n)scanf("%d",val+i);
    init();
    scanf("%d",&q);
    while(q--){
	scanf("%d%d%d",&o,&ql,&qr);
	if(o) update(ql,qr);
	else  printf("%d\n",query(ql,qr));
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/jihe/p/6944674.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值