[JZOJ5863] 【NOIP2018模拟9.11】移动光标
感觉这题和在纪中时候打的一场CF的A题特别像。。。
其实就是维护区间最小值。然后画画图就行了。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define reg register inline char gc() { static const int BS = 1 << 22; static unsigned char buf[BS], *st, *ed; if (st == ed) ed = buf + fread(st = buf, 1, BS, stdin); return st == ed ? EOF : *st++; } #define gc getchar inline int read() { int res = 0;char ch=gc();bool fu=0; while(!isdigit(ch))fu|=(ch=='-'),ch=gc(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=gc(); return fu?-res:res; } int n, L[100005]; int st[100005*20][21]; inline int query(int l, int r) { int k = log(r - l + 1) / log(2); return min(st[l][k], st[r - (1 << k) + 1][k]); } int main() { // freopen("cusor.in", "r", stdin); // freopen("cusor.out", "w", stdout); n = read(); for (reg int i = 1 ; i <= n ; i ++) L[i] = read(); for (reg int i = 1 ; i <= n ; i ++) st[i][0] = L[i]; for (reg int j = 1 ; j <= 20 ; j ++) for (reg int i = 1 ; i <= n - (1 << j) + 1 ; i ++) st[i][j] = min(st[i][j - 1], st[i + (1 << j - 1)][j - 1]); int q = read(); while(q--) { int x1 = read(), y1 = read(), x2 = read(), y2 = read(); if (x1 > x2) swap(x1, x2), swap(y1, y2); int mn = query(x1, x2); int ans = abs(x2 - x1); if (mn <= y1 and mn <= y2) ans += abs(y1 - mn) + abs(y2 - mn); else ans += abs(y1 - y2); printf("%d\n", ans); } return 0; }