Solution
Code(c++)
2064B - Variety is Discouraged:
Solution
Code(c++)
Solution
Code(c++)
Solution
Code(c++)
Solution
Code(c++)
Solution
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug(x) cout << #x << " = " << x << "\n";
#define vdebug(a) cout << #a << " = "; for(auto x: a) cout << x << " "; cout << "\n";
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int uid(int a, int b) { return uniform_int_distribution<int>(a, b)(rng); }
ll uld(ll a, ll b) { return uniform_int_distribution<ll>(a, b)(rng); }
template <class T> struct SegTree{
vector<T> seg;
int n;
const T ID = {INT_MAX, -INT_MAX};
T cmb(T a, T b){
array<int, 2> res;
res[0] = min(a[0], b[0]);
res[1] = max(a[1], b[1]);
return res;
}
SegTree(int _n){
n = 1;
while (n < _n) n *= 2;
seg.assign(2 * n + 1, ID);
}
void set(int pos, T val){
seg[pos + n] = val;
}
void build(){
for (int i = n - 1; i >= 1; i--) seg[i] = cmb(seg[2 * i], seg[2 * i + 1]);
}
void upd(int v, int tl, int tr, int pos, T val){
if (tl == tr){
seg[v] = val;
} else {
int tm = (tl + tr) / 2;
if (pos <= tm) upd(2 * v, tl, tm, pos, val);
else upd(2 * v + 1, tm + 1, tr, pos, val);
seg[v] = cmb(seg[2 * v], seg[2 * v + 1]);
}
}
void upd(int pos, T val){
upd(1, 0, n - 1, pos, val);
}
T query(int v, int tl, int tr, int l, int r){
if (l > r) return ID;
if (l == tl && r == tr) return seg[v];
int tm = (tl + tr) / 2;
T res = query(2 * v, tl, tm, l, min(tm, r));
res = cmb(res, query(2 * v + 1, tm + 1, tr, max(l, tm + 1), r));
return res;
}
T query(int l, int r){
return query(1, 0, n - 1, l, r);
}
};
void solve(){
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int &x : a) cin >> x;
vector<vector<int>> p(n + 1);
for (int i = 0; i < n; i++)
p[a[i]].push_back(i);
vector<array<int, 2>> stk;
vector<int> small_l(n, -1), small_r(n, n), big_l(n, -1), big_r(n, n);
for (int i = 0; i < n; i++){
while (stk.size() && a[i] <= stk.back()[0])
stk.pop_back();
if (stk.size())
small_l[i] = stk.back()[1];
stk.push_back({a[i], i});
}
stk.clear();
for (int i = n - 1; i >= 0; i--){
while (stk.size() && a[i] >= stk.back()[0])
stk.pop_back();
if (stk.size())
big_r[i] = stk.back()[1];
stk.push_back({a[i], i});
}
ll ans = 0;
SegTree<array<int, 2>> seg_small(n), seg_big(n);
for (int x = 1; x <= n; x++){
int y = k - x;
if (y > n){
for (int pos : p[x])
seg_small.upd(pos, {pos, pos});
continue;
}
vector<int> pre(p[y].size());
for (int i = 0; i < p[y].size(); i++){
if (i > 0)
pre[i] += pre[i - 1];
int r = big_r[p[y][i]] - 1;
if (i < p[y].size() - 1)
r = min(r, p[y][i + 1] - 1);
pre[i] += r - p[y][i] + 1;
}
vector<int> first(p[x].size()), last(p[y].size());
for (int i = 0; i < p[x].size(); i++)
first[i] = seg_small.query(p[x][i], n - 1)[0];
for (int i = 0; i < p[y].size(); i++)
last[i] = seg_big.query(0, p[y][i])[1];
int prev = -1;
for (int i = 0; i < p[x].size(); i++){
int l = p[x][i];
int l_min = small_l[l] + 1;
l_min = max(l_min, prev + 1);
prev = l;
int nxt = upper_bound(p[y].begin(), p[y].end(), l) - p[y].begin();
if (nxt == p[y].size())
continue;
int lo = nxt, hi = p[y].size();
while (lo < hi){
int mid = (lo + hi) / 2;
int pos = p[y][mid];
if (first[i] <= last[mid])
hi = mid;
else
lo = mid + 1;
}
lo--;
if (lo < nxt)
continue;
int res = pre[lo];
if (nxt > 0)
res -= pre[nxt - 1];
ans += 1LL * (l - l_min + 1) * res;
}
for (int pos : p[x])
seg_small.upd(pos, {pos, pos});
for (int pos : p[y])
seg_big.upd(pos, {pos, pos});
}
cout << ans << "\n";
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--) solve();
}