题目大意
查询一个区间输出最大值间最小值的差
用线段树写需要剪枝...本来明明是一道快乐的水题..却t了就用st写了..
线段树
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> const int maxn=3e5+5; using namespace std; int n,m; struct node{ int maxn,minn; } tree[maxn*4]; int arr[maxn],ans1,ans2; void built(int l,int r,int now) { int mid=(l+r)/2; if(l==r) { tree[now]=(node){arr[l],arr[l]}; return ; } built(l,mid,now*2); built(mid+1,r,now*2+1); tree[now].maxn=max(tree[now*2].maxn,tree[now*2+1].maxn); tree[now].minn=min(tree[now*2].minn,tree[now*2+1].minn); } void query(int l,int r,int left,int right,int now) { if(ans1>=tree[now].maxn&&ans2<=tree[now].minn) return ;//剪枝 int mid=(l+r)/2; if(l>right) return ; if(r<left) return ; if(left<=l&&r<=right) { ans1=max(ans1,tree[now].maxn); ans2=min(ans2,tree[now].minn); } if(l==r) return ; query(l,mid,left,right,now*2); query(mid+1,r,left,right,now*2+1); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",arr+i); } built(1,n,1); // for(int i=1;i<=24;i++) // { // cout<<tree[i].maxn<<endl; // } for(int i=1;i<=m;i++) { int l,r; scanf("%d%d",&l,&r); ans1=0,ans2=0x7fffffff; query(1,n,l,r,1); //cout<<ans1<<" "<<ans2<<endl; printf("%d\n",ans1-ans2); } return 0; }
st表
#include<cstdio> #include<cmath> #include<iostream> using namespace std; int a[100005],maxn[100005][35],minn[100005][35],n,m; void f(){ int k=log(n)/log(2)+1; for(int j=1;j<=k;j++) { for(int i=1;i<=n;i++) { if( i + (1 << j) - 1 <= n) maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]); minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]); } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); maxn[i][0]=a[i]; minn[i][0]=a[i]; } f(); while(m--) { int l,r; scanf("%d%d",&l,&r); int k=log(r-l+1)/log(2); //cout<<k<<endl; printf("%d\n",max(maxn[l][k],maxn[r-(1<<k)+1][k])-min(minn[l][k],minn[r-(1<<k)+1][k])); } return 0; }
来源:https://www.cnblogs.com/minun/p/10473772.html