【LOJ10121】與眾不同
阿新 • • 發佈:2018-12-28
【LOJ10121】與眾不同
題面
題解
這題是_\(tham\)給\(ztl\)他們做的,然而這道題™居然還想了蠻久。。。
首先可以尺取出一個位置\(i\)上一個合法的最遠位置\(pre_i\)
而對於一個詢問\((l,r)\),因為\(pre_i\)是單調的
所以可以二分出\(pre_i\geq l\)的第一個位置\(mid\)
用\(st\)表維護一下區間\(i-pre_i+1\)最大值\(qmax\)
則\(ans=max(mid-l,qmax(mid,r))\)
注意判斷一下邊界情況
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; inline int gi() { register int data = 0, w = 1; register char ch = 0; while (!isdigit(ch) && ch != '-') ch = getchar(); if (ch == '-') w = -1, ch = getchar(); while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); return w * data; } const int MAX_N = 200005; const int MAX_LOG_N = 19; const int MAX_V = 1e6; int bln[MAX_V << 1 | 1]; int N, M, a[MAX_N], pre[MAX_N]; int st[MAX_N][MAX_LOG_N], lg2[MAX_N]; void Prepare() { int l = 1, r = 0; do { bln[a[++r]]++; while (bln[a[r]] > 1) --bln[a[l++]]; pre[r] = l; } while (l <= N && r <= N && l <= r); for (int i = 1; i <= N; i++) st[i][0] = i - pre[i] + 1; for (int j = 1; j <= 18; j++) for (int i = 1; i + (1 << j) - 1 <= N; i++) st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]); for (int i = 2; i <= MAX_N; i++) lg2[i] = lg2[i >> 1] + 1; } int qmax(int l, int r) { int t = lg2[r - l + 1]; return max(st[l][t], st[r - (1 << t) + 1][t]); } int solve(int ql, int qr) { if (qmax(qr, qr) >= qr - ql + 1) return qr - ql + 1; int l = ql, r = qr, res = qr; while (l <= r) { int mid = (l + r) >> 1; if (ql <= pre[mid]) res = mid, r = mid - 1; else l = mid + 1; } return max(res - ql, qmax(res, qr)); } int main () { N = gi(), M = gi(); for (int i = 1; i <= N; i++) a[i] = gi() + MAX_V; Prepare(); while (M--) { int l = gi() + 1, r = gi() + 1; printf("%d\n", solve(l, r)); } return 0; }