bzoj 1699 [Usaco2007 Jan]Balanced Lineup排队
链接:
https://www.lydsy.com/JudgeOnline/problem.php?id=1699
思路:
水题,求区间最大最小值,然后减一下,求区间最大最小值线段树,树状数组,分块,莫队都可以,这里直接用分块写了,代码量比较小。
分块写法:
#include<bits/stdc++.h> using namespace std; const int M = 1e5+10; const int inf = 1e9+10; int n,m,a[M],mn[M],mx[M],bl[M],block; int query(int l,int r){ int ans,maxx = 0,minn = inf; for(int i = l;i <= min(bl[l]*block,r);i ++){ minn = min(minn,a[i]); maxx = max(maxx,a[i]); } if(bl[l] != bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++){ minn = min(minn,a[i]); maxx = max(maxx,a[i]); } } for(int i = bl[l] + 1;i <= bl[r]-1;i ++){ minn = min(mn[i],minn); maxx = max(mx[i],maxx); } return maxx - minn; } int main() { int l,r; scanf("%d%d",&n,&m); block = sqrt(n); memset(mn,inf,sizeof(mn)); for(int i = 1;i <= n;i ++) scanf("%d",&a[i]); for(int i = 1;i <= n;i ++){ bl[i] = (i - 1)/block + 1; mn[(i-1)/block+1] = min(a[i],mn[(i-1)/block+1]); mx[(i-1)/block+1] = max(a[i],mx[(i-1)/block+1]); } for(int i = 1;i <= m;i ++){ scanf("%d%d",&l,&r); printf("%d\n",query(l,r)); } return 0; }
耗时: