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; }