QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#645342 | #8577. 평균 최대화 | user10086 | 7 | 127ms | 140784kb | C++23 | 9.9kb | 2024-10-16 17:51:26 | 2024-10-16 17:51:32 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 3e5 + 10;
int n, idx, l[N], r[N], a[N], s[N], rx[N], rs[N];
// #define __int128 int
int pc;
__int128 gcd(__int128 a, __int128 b)
{
if (a == 0) return b;
if (b == 0) return a;
int az = __builtin_ctzll(a & 0xffffffffffffffff);
int bz = __builtin_ctzll(b & 0xffffffffffffffff);
int shift = min(az, bz);
b >>= bz;
while (a != 0) {
a >>= az;
__int128 diff = b - a;
az = __builtin_ctzll(diff & 0xffffffffffffffff);
b = min(a, b);
a = diff < 0 ? -diff : diff;
}
return b << shift;
}
struct F
{
__int128 i, j;
F()
{
i = j = 0;
}
F(__int128 a, __int128 b)
{
i = a, j = b;
__int128 d = gcd(i, j);
i /= d, j /= d;
}
bool operator> (const F& f2) const
{
return i * f2.j > j * f2.i;
}
bool operator< (const F& f2) const
{
return i * f2.j < j * f2.i;
}
F operator + (const F& f2) const
{
return {i * f2.j + j * f2.i, j * f2.j};
}
}ans[N];
struct V
{
__int128 x, y;
V operator+ (const V& v2) const
{
return {x + v2.x, y + v2.y};
}
bool operator< (const V& v2) const
{
return y * v2.x < x * v2.y;
}
bool operator> (const V& v2) const
{
return y * v2.x > x * v2.y;
}
};
mt19937 rng(20241015);
namespace Tree
{
const int R = 2;
int idx;
int ls[N * R], rs[N * R], sz[N * R];
V val[N * R], sum[N * R];
void init()
{
val[0] = sum[0] = {0, 0};
}
int newnode(V v)
{
idx++;
assert(idx < N * R);
ls[idx] = rs[idx] = 0, sz[idx] = 1;
val[idx] = sum[idx] = v;
return idx;
}
inline void pushup(int u)
{
if (!u) return;
sum[u] = sum[ls[u]] + val[u] + sum[rs[u]];
sz[u] = sz[ls[u]] + 1 + sz[rs[u]];
}
// inline void apply(int u, const F& dass)
// {
// if (!u) return;
// sum[u] = {dass.i * sz[u], dass.j}, val[u] = dass;
// tass[u] = dass;
// }
//
// inline void pushdown(int u)
// {
// if (!u) return;
// if (tass[u].i == 0) return;
// apply(ls[u], tass[u]), apply(rs[u], tass[u]);
// tass[u] = {0, 1};
// }
array<int, 2> splitr(int u, int k)
{
// [1, k], [k+1, inf)
// printf("splitr(%lld, %lld)\n", u, k);
if (!u) return {0, 0};
if (sz[ls[u]] >= k)
{
auto res = splitr(ls[u], k);
ls[u] = res[1];
pushup(u);
return {res[0], u};
}
else
{
auto res = splitr(rs[u], k - sz[ls[u]] - 1);
rs[u] = res[0];
pushup(u);
// printf("&&&");
return {u, res[1]};
}
}
array<int, 2> splitv(int u, const V& v)
{
// [1, v] [v, inf)
if (!u) return {0, 0};
if (v > val[u])
{
auto res = splitv(ls[u], v);
ls[u] = res[1];
pushup(u);
return {res[0], u};
}
else
{
auto res = splitv(rs[u], v);
rs[u] = res[0];
pushup(u);
return {u, res[1]};
}
}
int merge(int l, int r)
{
// printf("merge(%lld, %lld)\n", l, r);
if (!l) swap(l, r);
if (!r) return l;
if (rng() % (sz[l] + sz[r]) < sz[l])
{
rs[l] = merge(rs[l], r);
pushup(l);
return l;
}
else
{
ls[r] = merge(l, ls[r]);
pushup(r);
return r;
}
}
inline void insert(int& rt, const V& v)
{
auto res = splitv(rt, v);
int c = newnode(v);
rt = merge(merge(res[0], c), res[1]);
}
// inline void assign(int& rt, int pos, const F& v)
// {
// auto res = splitr(rt, pos);
// apply(res[0], v);
// rt = merge(res[0], res[1]);
// }
// inline F qsum(int rt, int pos)
// {
// if (!rt) return {0, 1};
// pushdown(rt);
// if (pos <= sz[ls[rt]]) return qsum(ls[rt], pos);
// else return sum[ls[rt]] + val[rt] + qsum(rs[rt], pos - sz[ls[rt]] - 1);
//// auto res = splitr(rt, pos);
//// printf("qsum(%lld, %lld)\n", rt, pos);
//// F ret = sum[res[0]];
//// rt = merge(res[0], res[1]);
//// return ret;
// }
//
// const F& kth(int rt, int k)
// {
// int p = sz[ls[rt]];
// pushdown(rt);
// if (k <= p) return kth(ls[rt], k);
// else if (k > p + 1) return kth(rs[rt], k - sz[ls[rt]] - 1);
// else return val[rt];
//// auto res = splitr(rt, k);
//// auto res2 = splitr(res[0], k - 1);
//// F ret = val[res2[1]];
//// rt = merge(merge(res2[0], res2[1]), res[1]);
//// return ret;
// }
void print(int rt)
{
if (!rt) return;
print(ls[rt]), printf("node %lld: sum = %lld/%lld, val = %lld/%lld, ls = %lld, rs = %lld\n", rt, sum[rt].y, sum[rt].x, val[rt].y, val[rt].x, ls[rt], rs[rt]), print(rs[rt]);
}
void pop(int& rt)
{
auto res = splitr(rt, 1);
rt = res[1];
}
V front(int& rt)
{
auto res = splitr(rt, 1);
V ret = val[res[0]];
rt = merge(res[0], res[1]);
return ret;
}
}
int pc2;
int dp[N];
vector<int> son[N];
vector<int> rg[N];
map<array<int, 2>, int> mp;
int build(int l, int r)
{
idx++, ::l[idx] = l, ::r[idx] = r, mp[{l, r}] = idx;
int x = idx; rx[x] = r - l + 1, rs[x] = s[r] - s[l - 1];
for (int i = l; i <= r; i++)
{
if (rg[i].empty()) continue;
int j = rg[i].back(); rg[i].pop_back();
int y = build(i, j);
son[x].push_back(y);
rx[x] -= (j - i + 1), rs[x] -= (s[j] - s[i - 1]);
i = j;
}
return x;
}
template<class T>
void chkmax(T &x, T y)
{
if (y > x) x = y;
}
void merge(int& a, int b)
{
if (!b) return;
merge(a, Tree::ls[b]), merge(a, Tree::rs[b]);
Tree::ls[b] = Tree::rs[b] = 0, Tree::sz[b] = 1, Tree::sum[b] = Tree::val[b];
auto res = Tree::splitv(a, Tree::val[b]);
a = Tree::merge(Tree::merge(res[0], b), res[1]);
}
void getp(int rt, int a, int b, V cur, int rk, V& ans)
{
// printf("getp(%lld, %lld, %lld, {%lld, %lld}, %lld)\n", rt, a, b, cur.i, cur.j, rk);
if (!rt) return;
V f = cur + Tree::sum[Tree::ls[rt]], d = Tree::val[rt];
f.y -= b, f.x -= a;
// printf("f\' = {%lld, %lld}, d = {%lld, %lld}\n", f.i, f.j, d.i, d.j);
if (f > d) getp(Tree::ls[rt], a, b, cur, rk, ans);
else
{
ans = cur + Tree::sum[Tree::ls[rt]] + Tree::val[rt];
getp(Tree::rs[rt], a, b, cur + Tree::sum[Tree::ls[rt]] + Tree::val[rt], rk + Tree::sz[Tree::ls[rt]] + 1, ans);
}
}
// pair<int, F> getp(int rt, int a, int b)
// {
// // max (y - b) / (x - a)
// int l = 0, r = Tree::sz[rt];
// auto getres = [&](int x)
// {
// F y1 = Tree::qsum(rt, x);
// y1.i -= b * y1.j, y1.j *= (x - a);
// // y1.reduce();
// return y1;
// };
// int dpc = 0;
// while (l < r)
// {
// // int mid1 = (l + r) >> 1, mid2 = mid1 + 1;
// dpc += 2;
// int mid = (l + r) >> 1;
// F f = Tree::qsum(rt, mid), d = Tree::kth(rt, mid + 1);
// f.i -= b * f.j, f.j *= (mid - a);
// if (f > d) r = mid;
// else l = mid + 1;
// }
// // printf(")))"), Tree::print(rt);
// // printf("res(l) = (%lld, %lld/%lld), res(r) = (%lld, %lld/%lld)\n", l, getres(l).i, getres(l).j, r, getres(r).i, getres(r).j);
// dpc++;
// assert(dpc < 19 * 2 + 1);
// pc2 += dpc;
// auto resl = getres(l);
// return {l, resl};
// }
void dfs(int x)
{
// printf("dfs(%lld): [%lld, %lld]\n", x, l[x], r[x]);
dp[x] = 0;
if (son[x].empty()) Tree::insert(dp[x], {rx[x], rs[x]});
else
{
for (int y : son[x])
{
dfs(y);
if (Tree::sz[dp[x]] < Tree::sz[dp[y]]) swap(dp[x], dp[y]);
merge(dp[x], dp[y]);
}
if (x == 1) return;
// Tree::print(dp[x]);
// (-rx[x], -rs[x])
//printf("getp(%lld)\n", x);
V res = {0, 0};
getp(dp[x], -rx[x], -rs[x], {0, 0}, 0, res);
// printf("proc: res = {%lld, %lld}\n", res.y, res.x);
V sum = {0, 0};
while (Tree::sz[dp[x]] && sum.x <= res.x) sum = sum + Tree::front(dp[x]), Tree::pop(dp[x]);
res.x += rx[x], res.y += rs[x];
Tree::insert(dp[x], res);
// int p = res.first;
// F v = res.second;
// Tree::assign(dp[x], p, v);
// for (int i = 1; i <= rx[x]; i++) Tree::insert(dp[x], v);
}
// Tree::print(dp[x]);
// cout << "***";
// assert(pc < 3.5e7);
V res = {0, 0};
getp(dp[x], -2, -(a[l[x] - 1] + a[r[x] + 1]), {0, 0}, 0, res);
res.x += 2, res.y += (a[l[x] - 1] + a[r[x] + 1]);
ans[x] = {res.y, res.x};
// printf("%lld: (%lld, %lld)\n", x, ans[x].i, ans[x].j);
}
bool flag;
void initialize(vector<signed> A)
{
n = (int)(A.size());
for (int i = 1; i <= n; i++) a[i] = A[i - 1];
for (int i = 1; i <= n; i++) s[i] = a[i] + s[i - 1];
vector<int> s;
for (int i = n; i >= 1; i--)
{
while (!s.empty() && a[s.back()] > a[i])
{
int x = s.back(); s.pop_back();
if (x != i + 1) rg[i + 1].push_back(x - 1);
}
if (!s.empty() && s.back() != i + 1) rg[i + 1].push_back(s.back() - 1);
if (!s.empty() && a[s.back()] >= a[i]) s.pop_back();
s.push_back(i);
}
// for (int i = 1; i <= n; i++)
// for (int j : rg[i]) printf("[%lld, %lld]\n", i, j);
build(2, n - 1);
// for (int i = 1; i <= n; i++)
// printf("rx[%lld] = %lld, rs[%lld] = %lld\n", i, rx[i], i, rs[i]);
Tree::init();
if (!flag) dfs(1);
// for (int i = 1; i <= n; i++)
// for (int j = 0; j <= sz[i]; j++)
// printf("dp[%lld][%lld] = %lld\n", i, j, dp[i][j]);
// for (int i = 1; i <= n; i++)
// for (int j : son[i]) printf("[%lld, %lld] -> [%lld, %lld]\n", l[i], r[i], l[j], r[j]);
}
array<long long, 2> maximum_average(signed i, signed j)
{
i++, j++;
if (j == i + 1) return {a[i] + a[j], 2};
assert(mp.find({i + 1, j - 1}) != mp.end());
int id = mp[{i + 1, j - 1}];
if (flag) return {idx, ans[id].j};
return {ans[id].i, ans[id].j};
}
// signed main()
// {
// cin.tie(0)->sync_with_stdio(0);
//
// int n; cin >> n;
// vector<signed> A;
// for (int i = 1, ai; i <= n; i++) cin >> ai, A.push_back(ai);
//// for (int i = 1, ai; i <= n; i++) A.push_back(rng() % 20 + 1);
// initialize(A);
// printf("idx = %lld, pc = %lld, pc2 = %lld, time = %lld\n", idx, pc, pc2, (int)clock());
// int l, r;
// while (cin >> l >> r)
// {
// auto res = maximum_average(l, r);
// cout << res[0] << ' ' << res[1] << '\n';
// }
// }
Details
Tip: Click on the bar to expand more detailed information
Subtask #1:
score: 0
Wrong Answer
Test #1:
score: 5
Accepted
time: 0ms
memory: 36848kb
input:
10 2 4 3 9 9 9 9 9 9 1 2 0 2 0 9
output:
3 1 20 3
result:
ok correct!
Test #2:
score: 0
Wrong Answer
time: 0ms
memory: 36880kb
input:
15 4596730 8340349 4612555 5692442 3914918 5213545 5248236 1276073 3844119 2943960 9231647 5091649 2239006 9139001 4735414 100 7 8 5 6 2 4 0 4 8 9 10 11 3 4 0 1 10 11 10 11 3 4 4 5 12 13 0 2 2 4 11 12 12 14 2 3 7 8 12 14 6 7 4 5 11 12 10 11 7 12 8 9 8 9 0 2 2 3 12 14 7 9 7 9 12 13 10 11 9 11 13 14 8...
output:
5120192 2 10461781 2 14219915 3 5366138 1 6788079 2 14323296 2 9607360 2 12937079 2 14323296 2 14323296 2 9607360 2 9128463 2 11378007 2 5849878 1 14219915 3 7330655 2 16113421 3 10304997 2 5120192 2 16113421 3 6524309 2 9128463 2 7330655 2 14323296 2 4156467 1 6788079 2 6788079 2 5849878 1 10304997...
result:
wrong answer Wrong Answer on query #4: 5366138/1 != 27156994/5
Subtask #2:
score: 0
Skipped
Dependency #1:
0%
Subtask #3:
score: 0
Skipped
Dependency #2:
0%
Subtask #4:
score: 7
Accepted
Test #15:
score: 7
Accepted
time: 103ms
memory: 59500kb
input:
300000 1 2 4 4 4 4 3 2 4 4 3 4 4 4 4 4 4 4 4 4 3 4 3 4 4 4 4 4 4 4 4 3 3 4 4 4 3 4 3 4 4 4 4 4 4 4 4 4 4 3 3 4 4 4 3 4 4 3 4 4 4 4 4 4 4 3 2 4 4 4 4 4 4 4 4 4 4 4 4 4 3 4 4 4 4 4 4 4 4 4 4 4 2 4 4 2 4 4 3 4 4 4 2 3 4 4 4 4 4 4 3 2 4 4 4 2 4 4 4 4 4 4 4 4 4 4 4 2 4 4 4 4 4 4 3 4 4 3 4 4 4 4 4 4 4 4 4...
output:
1041675 278497 23 7 3 2 8 2 6 2 8 2 8 2 7 2 5 2 7 2 56 15 8 2 6 2 7 2 42 11 13 4 8 2 7 2 8 2 8 2 8 2 8 2 8 2 8 2 8 2 7 2 10 3 7 2 7 2 19 5 8 2 7 2 8 2 8 2 8 2 8 2 8 2 8 2 7 2 6 2 18 5 8 2 7 2 8 2 7 2 10 3 7 2 7 2 23 6 8 2 7 2 8 2 8 2 8 2 8 2 8 2 8 2 8 2 8 2 7 2 6 2 18 5 8 2 7 2 8 2 7 2 7 2 8 2 7 2 7...
result:
ok correct!
Subtask #5:
score: 0
Skipped
Dependency #3:
0%
Subtask #6:
score: 0
Wrong Answer
Test #28:
score: 0
Wrong Answer
time: 123ms
memory: 140784kb
input:
300000 1 300000 300001 299999 300003 299998 300005 299997 300007 299996 300009 299995 300011 299994 300013 299993 300015 299992 300017 299991 300019 299990 300021 299989 300023 299988 300025 299987 300027 299986 300029 299985 300031 299984 300033 299983 300035 299982 300037 299981 300039 299980 3000...
output:
750001 4
result:
wrong answer Wrong Answer on query #1: 750001/4 != 917250302/2450
Subtask #7:
score: 0
Wrong Answer
Dependency #4:
100%
Accepted
Test #44:
score: 0
Wrong Answer
time: 127ms
memory: 69996kb
input:
300000 1 18 20 20 20 18 20 19 19 20 20 20 20 20 20 20 20 20 20 20 20 20 13 20 18 20 20 20 20 20 20 20 16 20 20 20 20 20 20 19 18 20 20 20 20 20 18 20 20 20 20 19 20 20 20 20 20 20 20 20 20 20 14 19 20 20 19 20 20 20 19 19 20 18 18 12 20 19 20 20 20 20 20 20 20 11 20 20 14 20 19 19 20 20 20 20 20 20 ...
output:
280051 14348 96 5 19 2 40 2 38 2 40 2 38 2 349 18 39 2 38 2 38 2 19 1 292 15 40 2 39 2 40 2 40 2 40 2 40 2 40 2 40 2 40 2 40 2 40 2 40 2 40 2 33 2 269 14 428 23 38 2 33 2 58 3 17 1 40 2 38 2 40 2 40 2 40 2 40 2 40 2 36 2 604 31 207 11 40 2 36 2 40 2 40 2 40 2 40 2 39 2 37 2 155 8 136 7 173 9 40 2 38...
result:
wrong answer Wrong Answer on query #1: 280051/14348 != 398307/20360
Subtask #8:
score: 0
Skipped
Dependency #1:
0%