洛谷P1816 忠诚 分块
分块真的是很暴力呀…
暴力查询左端,暴力查询又端点,中间整体部分直接 $O(1)$ 求出。
注意编程细节:belong[i]=(i−1)/block+1,这样可以保证序列被分成这样的:
Code:
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> using namespace std; const int maxn = 1000000; const int inf = 100000000; int n,m; struct Data_Structrue{ int arr[maxn], minv[maxn], belong[maxn]; int block; inline void build(){ memset(minv, 127, sizeof(minv)); scanf("%d%d",&n,&m); block = sqrt(n); for(int i = 1;i <= n; ++i){ scanf("%d",&arr[i]); belong[i] = (i - 1)/ block + 1; minv[belong[i]] = min(minv[belong[i]], arr[i]); } } inline int query(int l,int r){ int minn = inf; for(int i = l;i <= min(belong[l] * block, r); ++i) minn = min(minn, arr[i]); //暴力查询左端(可能已经查询完毕) if(belong[l] != belong[r]) { for(int i = (belong[r] - 1) * block + 1;i <= r; ++i) //暴力查询右端 minn = min(minn, arr[i]); } for(int i = belong[l] + 1;i < belong[r]; ++i) minn = min(minn, minv[i]); //中间部分直接查询 return minn; } }T; int main(){ //freopen("input.in","r",stdin); T.build(); while(m--){ int a,b; scanf("%d%d",&a,&b); printf("%d ", T.query(a,b)); } return 0; }