思路:我们定义F(x) 为以x点为起点,向后(a - b)个里面有多少个白球,虽然x的范围是LL范围内的,但是白球的
个数只有1e5, 那么我们可以把连续一段相同的离散化到一起, 对于一个确定的长度为a的段, Bob选择留下F(x)
最小的那一个,这个可以用st表求出来, 那么对于Alice来说,对于函数F(x)离散化到一起的值域(p - q) , 我们如果
要在(p - q)之间选一个起点那么p这个点是最优的点。那么我们枚举这些p,选一个答案的最大值。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define PLI pair<LL, int> #define ull unsigned long long using namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; ull n, L, R, a, b, c, dis, tot, p[N], range[N]; int f[N], Log[N]; struct ST { int dp[N][20],ty; void build(int n, int b[], int _ty) { ty = _ty; for(int i = 1; i <= n; i++) dp[i][0] = ty*b[i]; for(int j = 1; j <= Log[n]; j++) for(int i = 1; i+(1<<j)-1 <= n; i++) dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]); } int query(int x, int y) { if(x > y) return 0; int k = Log[y - x + 1]; return ty * max(dp[x][k], dp[y-(1<<k)+1][k]); } } rmq; int main() { for(int i = -(Log[0]=-1); i < N; i++) Log[i] = Log[i - 1] + ((i & (i - 1)) == 0); while(scanf("%llu", &n) != EOF) { tot = 0; scanf("%llu%llu%llu%llu", &L, &R, &a, &b); for(int i = 1; i <= n; i++) scanf("%llu", &p[i]); if(a == b) { puts("0"); } else { c = a - b; for(ull i = L, j = 1, k = 1; i <= R; i += dis) { while(k <= n && i > p[k]) k++; while(j <= n && i+c-1 >= p[j]) j++; f[++tot] = j - k; dis = R - i + 1; if(k <= n) dis = min(dis, p[k]-i+1); if(j <= n) dis = min(dis, p[j]-i-c+1); range[tot] = i; } rmq.build(tot, f, -1); int ans = 0; for(int i = 1, j = 1; i <= tot; i++) { if(range[i]+a-1 > R) break; while(j <= tot && range[j] <= range[i]+a-c) j++; ans = max(ans, rmq.query(i, j-1)); } printf("%llu ", ans); } } return 0; } /* */