CF2009G2 Yunli's Subarray Queries (hard version)
首先考虑计算
处理好了第一个长度为 *s.rbegin()
就是
hard version 式子的意思可以理解为:对于给定的询问
为此,我们先把询问离线下来,按区间左端点排序,然后从后往前遍历每个长度为
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define dep(i, a, b) for (int i = a; i >= b; i--)
#define endl '\n'
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vll = vector<ll>;
struct seg {
vi L, R, tag;
vll sum;
#define ls p << 1
#define rs p << 1 | 1
#define mid ((L[p] + R[p]) >> 1)
seg(int n)
: L(n * 4 + 10), R(n * 4 + 10), sum(n * 4 + 10), tag(n * 4 + 10) {
bld(1, 1, n);
}
void up(int p) { sum[p] = sum[ls] + sum[rs]; }
void bld(int p, int l, int r) {
L[p] = l, R[p] = r, tag[p] = -1;
if (l == r) return;
bld(ls, l, mid);
bld(rs, mid + 1, r);
up(p);
}
void atg(int p, ll v) { tag[p] = v, sum[p] = v * (R[p] - L[p] + 1); }
void pd(int p) {
if (tag[p] == -1) return;
atg(ls, tag[p]), atg(rs, tag[p]);
tag[p] = -1;
}
void upd(int p, int l, int r, int v) {
if (l <= L[p] && R[p] <= r) return atg(p, v), void();
pd(p);
if (l <= mid) upd(ls, l, r, v);
if (r > mid) upd(rs, l, r, v);
up(p);
}
ll ask(int p, int l, int r) {
if (l <= L[p] && R[p] <= r) return sum[p];
pd(p);
ll res = 0;
if (l <= mid) res += ask(ls, l, r);
if (r > mid) res += ask(rs, l, r);
return res;
}
#undef ls
#undef rs
#undef mid
};
struct qry {
int l, r, id;
bool operator<(const qry& o) const {
return l < o.l;
}
};
void solve() {
int n, k, m;
cin >> n >> k >> m;
vi a(n + 1);
rep(i, 1, n) cin >> a[i];
map<int, int> mp;
multiset<int> s;
rep(i, 1, n) s.insert(0);
rep(i, 1, k - 1) {
s.erase(s.find(mp[a[i] - i]));
mp[a[i] - i]++;
s.insert(mp[a[i] - i]);
}
int K = n - k + 1;
vi c(K + 1);
rep(i, k, n) {
s.erase(s.find(mp[a[i] - i]));
mp[a[i] - i]++;
s.insert(mp[a[i] - i]);
int p = i - k + 1;
c[p] = k - *s.rbegin();
s.erase(s.find(mp[a[p] - p]));
mp[a[p] - p]--;
s.insert(mp[a[p] - p]);
}
vector<qry> q(m + 1);
rep(i, 1, m) {
q[i].id = i;
cin >> q[i].l >> q[i].r;
}
sort(q.begin() + 1, q.end());
seg tr(K); // i维护前缀l~i最小步数
stack<int> st; // 单调栈
vll ans(m + 1);
int j = m;
dep(i, K, 1) {
while (!st.empty() && c[st.top()] >= c[i]) st.pop();
int end = st.empty() ? K : st.top() - 1;
st.push(i);
tr.upd(1, i, end, c[i]);
for (; j && q[j].l == i; j--)
ans[q[j].id] = tr.ask(1, q[j].l, q[j].r - k + 1);
}
rep(i, 1, m) cout << ans[i] << endl;
}
int32_t main(int t = 1) {
cin >> t;
while (t--) solve();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】