program P1038; const MaxN=100000; type tre=record lc,rc,l,r,mindata:longint; end; var m,n,root,tot:longint; tree:array [-1..MaxN*4] of tre; procedure build(var t:longint;l,r:longint); begin inc(tot); t:=tot; tree[t].l:=l; tree[t].r:=r; tree[t].mindata:=maxlongint;//首先是建树的过程,我们要找一段区间内的最小值,那么先把每个区间都设成最大值 if l=r then exit; if l<r then begin build(tree[t].lc,l,(l+r) div 2); build(tree[t].rc,(l+r) div 2+1,r); end; end; function min(x,y:longint):longint; begin if x>y then exit(y) else exit(x); end; procedure insert(t,data,l,r:longint); begin if t=0 then exit; if (l=tree[t].l) and (r=tree[t].r) then begin tree[t].mindata:=min(tree[t].mindata,data);//如果左右边界与左右区间重合取最小值覆盖区间并退出 exit; end; if (l>=tree[t].l) and (r<=tree[t].r) then tree[t].mindata:=min(tree[t].mindata,data);如果树能完全覆盖区间也进行更新 if l>=tree[tree[t].rc].l then insert(tree[t].rc,data,l,r) else if r<=tree[tree[t].lc].r then insert(tree[t].lc,data,l,r) else begin insert(tree[t].lc,data,l,tree[tree[t].lc].r); insert(tree[t].rc,data,tree[tree[t].rc].l,r); end; end; function find(t,l,r:longint):longint; begin if t=0 then exit; if (tree[t].l=l) and (tree[t].r=r) then exit(tree[t].mindata);//重合直接出最小值 if r<=tree[tree[t].lc].r then exit(find(tree[t].lc,l,r)) else if l>=tree[tree[t].rc].l then exit(find(tree[t].rc,l,r)) else exit(min(find(tree[t].lc,l,tree[tree[t].lc].r),find(tree[t].rc,tree[tree[t].rc].l,r)));//否则在左右两子树中取最小值 end; procedure init; var i,x,y:longint; begin root:=0; tot:=0; readln(m,n); build(root,1,m); for i:=1 to m do begin read(x); insert(root,x,i,i);//把一个左边界为i,且右边界为i的线段插入线段树,能确保不断更新线段的最小值 end; readln; for i:=1 to n do begin readln(x,y); write(find(root,x,y),' ');//找从x到y的最小值 end; end; begin assign(input,'P1038.in'); reset(input); assign(output,'P1038.out'); rewrite(output); init; close(input); close(output); end.