不条理狂诗曲
给出两个做法,一个平凡,一个大牛逼。
Sol1 分治
很常规吧,不说了。
Sol2 线性做法
考虑 \(f\) 为随便选不选 \(i\) 的方案,\(g\) 为一定不选 \(i\) 的方案。
转移:
\[f' \leftarrow \max(f, g + a_i), g' \leftarrow f
\]
很难搞,把前面的式子变下型:
\[f' \leftarrow f + \max(0, a_i - (f - g)), g' \leftarrow f
\]
发现了什么?
\(f \rightarrow f'\) 的变化值和 \(f' - g'\) 均为 \(\max(0, a_i - (f - g))\)!!!
那这个性质就很优美了啊,从左往右扫,记 \(r_x\) 为右端点为 \(x\) 的 \(f(l, r)\) 之和,考虑 \(r_{x - 1} \rightarrow r_x\) 的变化值 \(\Delta_x\),显然 \(\Delta_x = -\Delta_{x - 1} + xa_x\),如果不考虑和 \(0\) 去 \(\max\) 直接扫一遍就没了。
如果考虑,那么我们维护一个二元组组成的集合 \(S\),里面的每个二元组 \((x, y)\) 的 \(x\) 表示一个 \(f - g\), \(y\) 表示 \(f - g = x\) 个 \(f - g\) 有多少个。
显然 \(f - g\) 类似一次函数的复合,仍然是一次函数,可以对斜率和截距打一个全局 tag(这里斜率只能是 \(\{-1, 1\}\))。于是 \(S\) 在维护的过程中始终有序,证明就是归纳。
然后又有性质了,暴力将 \(S\) 中的负数删掉是对的,因为每次这么做都会减少一个元素,而最多插入 \(\mathcal{O}(n)\) 个元素,且 \(S\) 在维护过程中又是有序的,只需要考虑队头和队尾即可!!!
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
// typedef __int128 i128;
typedef pair<int, int> pii;
const int N = 2e5 + 10, mod = 1e9 + 7;
template<typename T>
void dbg(const T &t) { cout << t << endl; }
template<typename Type, typename... Types>
void dbg(const Type& arg, const Types&... args) {
cout << arg << ' ';
dbg(args...);
}
namespace Loop1st {
int n;
ll a[N], tx = 1, ty, sum, res, ans;
deque<pair<ll, int>>S; // 每次 decode 后 S 要么升序要么降序
ll decode(ll x) { return tx * x + ty; }
ll encode(ll x) { return (x - ty) / tx; } // * tx <=> / tx(tx \in {-1, 1})
void main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) {
if (S.empty() || encode(0) <= S.front().first) S.push_front({encode(0), 1});
else S.push_back({encode(0), 1}); // 这里是插入 f' - g'
tx = -tx; ty = -ty + a[i]; sum = (mod - sum + a[i] * i) % mod;
int cnt = 0;
while (!S.empty() && decode(S.front().first) < 0) {
sum = (sum + mod - decode(S.front().first) * S.front().second % mod) % mod;
cnt += S.front().second;
S.pop_front();
}
while (!S.empty() && decode(S.back().first) < 0) {
sum = (sum + mod - decode(S.back().first) * S.back().second % mod) % mod;
cnt += S.back().second;
S.pop_back();
}
// if (cnt) {
if (S.empty() || encode(0) <= S.front().first) S.push_front({encode(0), cnt});
else S.push_back({encode(0), cnt});
// }
res = (res + sum) % mod;
ans = (ans + res) % mod;
}
cout << ans << '\n';
}
}
int main() {
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int T = 1;
// cin >> T;
while (T--) Loop1st::main();
return 0;
}

浙公网安备 33010602011771号