AT_arc150_f [ARC150F] Constant Sum Subsequence
让所有
如何转移
我们直接分治转移,具体模仿 cdq 分治,先递归
现在考虑快速让
我们枚举
::::info[代码]
#include <bits/stdc++.h>
using namespace std;
#define PII pair<int, int>
#define _for(i, a, b) for (int i = (a); i <= (b); i++)
#define _pfor(i, a, b) for (int i = (a); i >= (b); i--)
#define int long long
const int N = 1e6 + 5e5 + 5;
int n, S, a[N], f[N];
vector<int> pos[N];
int nxt(int x, int y) {
int t = x % n, cnt = x / n * n;
if (t >= pos[y].back()) return cnt + pos[y].front() + n;
return cnt + *upper_bound(pos[y].begin(), pos[y].end(), t);
}
int pre(int x, int y) {
int t = x % n, cnt = x / n * n;
if (t <= pos[y].front()) return cnt - n + pos[y].back();
return cnt + *(--lower_bound(pos[y].begin(), pos[y].end(), t));
}
struct edge {
struct tt {
int l, r, maxn;
}tree[N * 4];
void build(int p, int l, int r) {
tree[p].l = l, tree[p].r = r;
if (l == r) return;
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
}
void modify(int p, int l, int r, int v) {
if (l <= tree[p].l && tree[p].r <= r) {
tree[p].maxn = max(tree[p].maxn, v);
return;
}
int mid = (tree[p].l + tree[p].r) >> 1;
if (l <= mid) modify(p << 1, l, r, v);
if (r > mid) modify(p << 1 | 1, l, r, v);
}
int query(int p, int x) {
if (tree[p].l == tree[p].r) return tree[p].maxn;
int mid = (tree[p].l + tree[p].r) >> 1, res = tree[p].maxn;
if (x <= mid) res = max(res, query(p << 1, x));
else res = max(res, query(p << 1 | 1, x));
return res;
}
}tr;
void solve(int l, int r) {
if (l >= r) return;
int mid = (l + r) >> 1;
solve(l, mid);
_for(k, 1, r - l) {
int R = min(mid, r - k);
int L = lower_bound(f + l, f + mid + 1, pre(f[R] + 1, k)) - f;
if (f[L] < pre(f[R] + 1, k)) continue;
L = max(mid + 1, L + k); R += k;
tr.modify(1, L, R, nxt(f[R - k], k));
}
_for(i, mid + 1, r) f[i] = max(f[i], tr.query(1, i));
solve(mid + 1, r);
}
signed main() {
cin >> n >> S;
tr.build(1, 1, S);
_for(i, 1, n) cin >> a[i], pos[a[i]].push_back(i);
solve(0, S);
cout << max(f[S], 1ll) << endl;
}
::::