【大联盟】20230703 T2 开心的序列(sequence) 题解 AT_agc049_f 【[AGC049F] Happy Sequence】
zak /bx
恐怖 zak 将这题加强,出到模拟赛。直接把 变成了 。
非常恐怖。
题目描述#
题解#
重新再理解一遍。
我们维护 ,那么就相当于要求 ,也就是 。
继续观察下。首先,显然需要满足 ,我们设这个数为 。那么,对于 的限制,我们设 为 的 个数、 为 的 的和、、 同理。
于是就得出,,化简可得 ,也就是要求 。
考虑 取在哪?一定是在 的位置,因为若 ,则 一定更优,若 ,则 一定更优。
所以,我们只需要关注 的位置,于是得出结论:满足条件当且仅当,对于排好序的 和 ,满足 ,且 。
我们令 ,条件为 。
这个结论赛时猜结论打表也发现了,不过完全没想到后面的。
我们发现:
- 让 增加 ,就相当于给 的 都增加 ,给 的 都减少 。
- 让 减少 ,就相当于给 的 都增加 ,给 的 都减少 。
于是,我们观察到让 小的数减少 ,并让 大的数增加 ,是一定不优的,假设增加的数为 ,减少的数为 ,并满足 ,则对于 或 , 都是不变的,而对于 , 却增加了 。
所以,一定存在一个 ,满足对于 左侧的数都在增加,对于 右侧的数都在减小。如果有多个 ,取 最大的(假设左侧最右的操作为 ,右侧最左的操作为 ,则 )。
观察到操作后 ,因为如果不满足条件,则可以通过删除 左侧第一个操作或右侧第一个操作,这样 就增加 了,仍然满足条件还,还更优。
不过,进一步地,由于需要满足 ,则说明 一定为偶数。因为 。
所以,可以得到 。
然后,我们发现,由于 左侧的数都在增加, 右侧的数都在减小。所以,每次操作都会让 变小,而 ,说明初始时 是最大值。
带入 ,可以得到 ,又因为 ,则说明左侧和相等,右侧和相等。
于是,左右就独立了,我们对左右分开做,形式相似(实际上只要把右侧取相反数就跟左侧形式完全一样了)。我们可以二分斜率 ,不过可能出现不合法,那么我们跟上面一样,找到 来处理。
则 左侧的斜率调整为 ,右侧调整为 ,像整体二分一样。
时间复杂度 。
代码#
记录。
#include <bits/stdc++.h>
#define SZ(x) (int) x.size() - 1
#define all(x) x.begin(), x.end()
#define ms(x, y) memset(x, y, sizeof x)
#define F(i, x, y) for (int i = (x); i <= (y); i++)
#define DF(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T> void chkmax(T& x, T y) { x = max(x, y); }
template <typename T> void chkmin(T& x, T y) { x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
template <typename T> void write(T x) {
if (x < 0) { putchar('-'); x *= -1; }
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
const int N = 2e5 + 10;
int n, b[N], g[N];
struct node {
ll cur;
int beg, val;
friend bool operator < (const node &x, const node &y) {
return x.cur < y.cur;
}
} t[N];
__int128 ans;
void solve(int l, int r, ll L, ll R) {
if (l > r) return;
ll mid = (L + R) >> 1;
F(i, l, r) t[i].cur = t[i].beg + (mid / t[i].val + 1) / 2;
sort(t + l, t + r + 1);
ll s = 0; int pos = r + 1;
DF(i, r, l) {
s += b[i] - t[i].cur;
if (s < 0) {
s = 0;
pos = i;
}
}
if (L + 1 == R) {
__int128 s = 0;
F(i, l, r) {
s += t[i].cur - b[i];
ans += (__int128) (t[i].cur - t[i].beg) * (t[i].cur - t[i].beg) * t[i].val;
} ans -= (__int128) s * R;
return;
} solve(l, pos - 1, mid, R), solve(pos, r, L, mid);
}
signed main() {
// freopen("sequence.in", "r", stdin);
// freopen("sequence.out", "w", stdout);
read(n);
F(i, 1, n) read(t[i].beg), t[i].cur = t[i].beg;
F(i, 1, n) read(b[i]);
sort(b + 1, b + n + 1);
F(i, 1, n) read(t[i].val);
sort(t + 1, t + n + 1);
ll s = 0; int pos = 0;
F(i, 1, n) {
s += t[i].beg - b[i];
if (s < 0) {
s = 0;
pos = i;
}
}
solve(1, pos, 0, 2e18 + 5);
reverse(t + pos + 1, t + n + 1);
reverse(b + pos + 1, b + n + 1);
F(i, pos + 1, n) t[i].beg = 1e9 - t[i].beg, b[i] = 1e9 - b[i];
solve(pos + 1, n, 0, 2e18 + 5);
write(ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话