이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include "closing.h"
#ifndef ATCODER_INTERNAL_TYPE_TRAITS_HPP
#define ATCODER_INTERNAL_TYPE_TRAITS_HPP 1
#include <cassert>
#include <numeric>
#include <type_traits>
namespace atcoder {
namespace internal {
#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
typename std::conditional<std::is_same<T, __int128_t>::value ||
std::is_same<T, __int128>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int128 =
typename std::conditional<std::is_same<T, __uint128_t>::value ||
std::is_same<T, unsigned __int128>::value,
std::true_type,
std::false_type>::type;
template <class T>
using make_unsigned_int128 =
typename std::conditional<std::is_same<T, __int128_t>::value,
__uint128_t,
unsigned __int128>;
template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
is_signed_int128<T>::value ||
is_unsigned_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
std::is_signed<T>::value) ||
is_signed_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int =
typename std::conditional<(is_integral<T>::value &&
std::is_unsigned<T>::value) ||
is_unsigned_int128<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using to_unsigned = typename std::conditional<
is_signed_int128<T>::value,
make_unsigned_int128<T>,
typename std::conditional<std::is_signed<T>::value,
std::make_unsigned<T>,
std::common_type<T>>::type>::type;
#else
template <class T> using is_integral = typename std::is_integral<T>;
template <class T>
using is_signed_int =
typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using is_unsigned_int =
typename std::conditional<is_integral<T>::value &&
std::is_unsigned<T>::value,
std::true_type,
std::false_type>::type;
template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
std::make_unsigned<T>,
std::common_type<T>>::type;
#endif
template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;
template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;
template <class T> using to_unsigned_t = typename to_unsigned<T>::type;
} // namespace internal
} // namespace atcoder
#endif // ATCODER_INTERNAL_TYPE_TRAITS_HPP
#ifndef ATCODER_FENWICKTREE_HPP
#define ATCODER_FENWICKTREE_HPP 1
#include <cassert>
#include <vector>
namespace atcoder {
// Reference: https://en.wikipedia.org/wiki/Fenwick_tree
template <class T> struct fenwick_tree {
using U = internal::to_unsigned_t<T>;
public:
fenwick_tree() : _n(0) {}
explicit fenwick_tree(int n) : _n(n), data(n) {}
void add(int p, T x) {
assert(0 <= p && p < _n);
p++;
while (p <= _n) {
data[p - 1] += U(x);
p += p & -p;
}
}
T sum(int l, int r) {
assert(0 <= l && l <= r && r <= _n);
return sum(r) - sum(l);
}
private:
int _n;
std::vector<U> data;
U sum(int r) {
U s = 0;
while (r > 0) {
s += data[r - 1];
r -= r & -r;
}
return s;
}
};
} // namespace atcoder
#endif // ATCODER_FENWICKTREE_HPP
#include <bits/stdc++.h>
using namespace std;
vector<vector<pair<int, int>>> adj;
struct SumCntFenwickTree {
SumCntFenwickTree(vector<pair<long long, int>> num)
: _bit_cnt(num.size()), _bit_sum(num.size()) {
for (auto [a, _] : num) {
_num.push_back(a);
}
}
void Add(int x) {
_bit_cnt.add(x, 1);
_bit_sum.add(x, _num[x]);
}
void Remove(int x) {
_bit_cnt.add(x, -1);
_bit_sum.add(x, -_num[x]);
}
int Cnt(int x) {
return _bit_cnt.sum(0, x);
}
long long Sum(int x) {
return _bit_sum.sum(0, x);
}
vector<long long> _num;
atcoder::fenwick_tree<int> _bit_cnt;
atcoder::fenwick_tree<long long> _bit_sum;
};
void fill_distance(int u, int from, vector<long long>& distance) {
for (auto [v, w] : adj[u]) {
if (v != from) {
distance[v] = distance[u] + w;
fill_distance(v, u, distance);
}
}
}
int non_intersecting(
int N, long long K,
const vector<long long>& fromX, const vector<long long>& fromY) {
vector<long long> smaller(N);
for (int i = 0; i < N; ++i) {
smaller[i] = min(fromX[i], fromY[i]);
}
sort(smaller.begin(), smaller.end());
for (int i = 0; i < N; ++i) {
if (smaller[i] <= K) {
K -= smaller[i];
} else {
return i;
}
}
return N;
}
int max_score(int N, int X, int Y, long long K,
std::vector<int> U, std::vector<int> V, std::vector<int> W) {
adj.clear();
adj.resize(N);
for (int i = 0; i < N - 1; ++i) {
adj[U[i]].emplace_back(V[i], W[i]);
adj[V[i]].emplace_back(U[i], W[i]);
}
vector<long long> fromX(N), fromY(N);
fill_distance(X, -1, fromX);
fill_distance(Y, -1, fromY);
vector<bool> is_in_path(N);
vector<int> in_path;
for (int i = 0; i < N; ++i) {
is_in_path[i] = fromX[i] + fromY[i] == fromX[Y];
if (is_in_path[i]) {
in_path.push_back(i);
}
}
int answer = non_intersecting(N, K, fromX, fromY);
for (int u : in_path) {
K -= min(fromX[u], fromY[u]);
}
if (K >= 0) {
vector<int> order(N);
iota(order.begin(), order.end(), 0);
sort(order.begin(), order.end(), [&] (int a, int b) {
return make_pair(max(fromX[a], fromY[a]) - min(fromX[a], fromY[a]), a)
< make_pair(max(fromX[b], fromY[b]) - min(fromX[b], fromY[b]), b);
});
vector<pair<long long, int>> cost_one, cost_two;
for (int i = 0; i < N; ++i) {
if (is_in_path[i]) {
cost_one.emplace_back(
max(fromX[i], fromY[i]) - min(fromX[i], fromY[i]), i);
} else {
cost_two.emplace_back(max(fromX[i], fromY[i]), i);
cost_one.emplace_back(min(fromX[i], fromY[i]), i);
}
}
sort(cost_one.begin(), cost_one.end());
sort(cost_two.begin(), cost_two.end());
vector<int> ix_cost_one(N), ix_cost_two(N);
for (int i = 0; i < N; ++i) {
ix_cost_one[cost_one[i].second] = i;
if (i < static_cast<int>(cost_two.size())) {
ix_cost_two[cost_two[i].second] = i;
}
}
SumCntFenwickTree bit_cost_one(cost_one);
SumCntFenwickTree bit_cost_two(cost_two);
for (int i = 0; i < N; ++i) {
if (!is_in_path[i]) {
bit_cost_one.Add(ix_cost_one[i]);
}
}
for (int i = 0; i < N; ++i) {
int u = order[i];
if (is_in_path[u]) {
bit_cost_one.Add(ix_cost_one[u]);
} else {
bit_cost_one.Remove(ix_cost_one[u]);
bit_cost_two.Add(ix_cost_two[u]);
}
auto check = [&] (int mid) {
int lowest_cannot_take = lower_bound(
cost_one.begin(),
cost_one.end(),
make_pair((cost_two[mid].first + 1) >> 1, 0)) - cost_one.begin();
return bit_cost_two.Sum(mid + 1)
+ bit_cost_one.Sum(lowest_cannot_take) <= K;
};
int take_until_two = -1;
{
int lo = 0;
int hi = static_cast<int>(cost_two.size()) - 1;
while (lo <= hi) {
int mid = (lo + hi) >> 1;
if (check(mid)) {
take_until_two = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
}
int take_until_one = -1;
if (false) {
while (take_until_one + 1 < N &&
bit_cost_two.Sum(take_until_two + 1)
+ bit_cost_one.Sum(take_until_one + 2) <= K)
++take_until_one;
} else {
int lo = 0;
int hi = N - 1;
while (lo <= hi) {
int mid = (lo + hi) >> 1;
if (bit_cost_two.Sum(take_until_two + 1)
+ bit_cost_one.Sum(mid + 1) <= K) {
take_until_one = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
}
answer = max(answer, static_cast<int>(in_path.size())
+ 2 * bit_cost_two.Cnt(take_until_two + 1)
+ bit_cost_one.Cnt(take_until_one + 1));
if (take_until_one >= 0) {
long long target_cost = bit_cost_one.Sum(take_until_one + 1);
{
take_until_one = -1;
int lo = 0;
int hi = N - 1;
while (lo <= hi) {
int mid = (lo + hi) >> 1;
if (bit_cost_one.Sum(mid + 1) < target_cost) {
take_until_one = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
}
int lo = 0;
int hi = static_cast<int>(cost_two.size()) - 1;
while (lo <= hi) {
int mid = (lo + hi) >> 1;
if (bit_cost_two.Sum(mid + 1)
+ bit_cost_one.Sum(take_until_one + 1) <= K) {
take_until_two = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
answer = max(answer, static_cast<int>(in_path.size())
+ 2 * bit_cost_two.Cnt(take_until_two + 1)
+ bit_cost_one.Cnt(take_until_one + 1));
}
}
}
return answer;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |