原题链接:
题意:
给你一个长度为N的序列A和两个数字 X X X, Y Y Y,问有多少个 [ L , R ] [L, R] [L,R]满足:
- 1 < = L < = R < = N 1<=L<=R<=N 1<=L<=R<=N
- m a x ( A L − R max(A_{L-R} max(AL−R) = X X X, m i n ( A L − R min(A_{L-R} min(AL−R) = Y Y Y
- 数据范围 N , A i , X , Y N, A_{i}, X, Y N,Ai,X,Y 均为 1 − 2 ∗ 1 0 5 1-2*10^{5} 1−2∗105
思路参考题解
- 首先对于序列中大于X和小于Y的数字一定是不能够包含在区间 [ L , R ] [L, R] [L,R]内的,据此可以根据将原序列分为若干个子序列 B B B,这样子序列内的数字大小全部都是在 [ X , Y ] [X, Y] [X,Y]内的,然后对这些子序列操作求解即可。
- 对于每一个子序列
B
B
B,该怎么求解有多少个区间中同时包含
X
,
Y
X, Y
X,Y呢,或许包含的不止一对,直接求解是不容易计算的,容斥原理,这时可以想到求解他的反例,即有多少区间只包含
X
X
X,有多少区间只包含
Y
Y
Y,或者有多少区间是
X
,
Y
X, Y
X,Y都不包含的。
我们想要找到的是“包含两者”的子序列的数量X和Y."可以表示如下:
(所有序列) −(不包含 X 的序列) −(不包含 Y 的序列) + (既不包含 X 也不包含 Y 的序列)。
const int N = 2e5+100;
int __[N], X_[N], _Y[N], XY[N];
int n;
ll f(int a[]) {
ll s = 0, t = 0;
for(int i = 1; i <= n; i++) {
if(a[i]) s += (t + 1) * t / 2, t = 0;
else t ++;
}
s += (t + 1) * t / 2;
return s;
}
void solve(){
int x, y; cin >> n >> x >> y;
vector<int> v(n + 1);
for(int i = 1; i <= n; i++) cin >> v[i];
for(int i = 1; i <= n; i++) {
if(!(v[i] >= y && v[i] <= x)) __[i] = X_[i] = _Y[i] = XY[i] = 1;
if(v[i] == x) X_[i] = XY[i] = 1;
if(v[i] == y) _Y[i] = XY[i] = 1;
}
ll re = f(__) - f(X_) - f(_Y) + f(XY);
cout << re << '\n';
}