QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#616635 | #7787. Maximum Rating | Kdlyh | WA | 1ms | 3728kb | C++20 | 6.9kb | 2024-10-06 09:26:26 | 2024-10-06 09:26:27 |
Judging History
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iterator>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include <stack>
#ifdef LOCAL
template <class T, size_t size = std::tuple_size<T>::value> std::string to_debug(T, std::string s = "") requires(not std::ranges::range<T>);
std::string to_debug(auto x) requires requires(std::ostream& os) { os << x; } { return static_cast<std::ostringstream>(std::ostringstream() << x).str(); }
std::string to_debug(std::ranges::range auto x, std::string s = "") requires(not std::is_same_v<decltype(x), std::string>) {
for (auto xi : x) { s += ", " + to_debug(xi); }
return "[" + s.substr(s.empty() ? 0 : 2) + "]";
}
template <class T, size_t size> std::string to_debug(T x, std::string s) requires(not std::ranges::range<T>) {
[&]<size_t... I>(std::index_sequence<I...>) { ((s += ", " + to_debug(get<I>(x))), ...); }(std::make_index_sequence<size>());
return "(" + s.substr(s.empty() ? 0 : 2) + ")";
}
#define debug(...) std::cerr << __LINE__ << ": (" #__VA_ARGS__ ") = " << to_debug(std::tuple(__VA_ARGS__)) << "\n"
#else
#define debug(x...)
#endif
using i64 = long long;
template <class T>
struct Discreter {
std::vector<T> elementSet;
Discreter(const std::vector<T> &a) : elementSet(a) {
std::sort(begin(elementSet), end(elementSet));
elementSet.erase(std::unique(begin(elementSet), end(elementSet)), end(elementSet));
}
std::vector<int> process(const std::vector<T> &a) const {//get the dicreter arr
std::vector<int> discRes(a.size());
for (int i = 0; i < a.size(); i++) {
discRes[i] = query(a[i]);
}
return discRes;
}
int query(const T &x) const {
auto it = std::lower_bound(begin(elementSet), end(elementSet), x);
// assert(it != end(elementSet) and *it == x);
return it - begin(elementSet);
}
int queryUpperBound(const T &x) const {
auto it = std::upper_bound(begin(elementSet), end(elementSet), x);
return it - begin(elementSet);
}
T queryInv(int index) const {
return elementSet[index];
}
int size() {
return elementSet.size();
}
};
template<class Info>
struct SegmentTree {
int n;
std::vector<Info> info;
SegmentTree() : n(0) {}
SegmentTree(int n_, Info v_ = Info()) {
init(n_, v_);
}
template<class T>
SegmentTree(std::vector<T> init_) {
init(init_);
}
void init(int n_, Info v_ = Info()) {
init(std::vector(n_, v_));
}
template<class T>
void init(std::vector<T> init_) {
n = init_.size();
info.assign(4 << std::__lg(n), Info());
std::function<void(int, int, int)> build = [&](int p, int l, int r) {
if (r - l == 1) {
info[p] = init_[l];
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m, r);
pull(p);
};
build(1, 0, n);
}
void pull(int p) {
info[p] = info[2 * p] + info[2 * p + 1];
}
void modify(int p, int l, int r, int x, const Info &v) {
if (r - l == 1) {
info[p] = info[p] + v;
return;
}
int m = (l + r) / 2;
if (x < m) {
modify(2 * p, l, m, x, v);
} else {
modify(2 * p + 1, m, r, x, v);
}
pull(p);
}
void modify(int p, const Info &v) {
modify(1, 0, n, p, v);
}
Info rangeQuery(int p, int l, int r, int x, int y) {
if (l >= y || r <= x) {
return Info();
}
if (l >= x && r <= y) {
return info[p];
}
int m = (l + r) / 2;
return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
}
Info rangeQuery(int l, int r) {
return rangeQuery(1, 0, n, l, r);
}
int findFirst(int p, int l, int r, int x, int y, i64 tar) {
if (l >= y || r <= x) {
return -1;
}
if (l >= x && r <= y && (info[p].sum <= tar)) {
return -1;
}
if (r - l == 1) {
return l;
}
int m = (l + r) / 2;
int res = findFirst(2 * p, l, m, x, y, tar);
if (res == -1) {
res = findFirst(2 * p + 1, m, r, x, y, tar - info[2 * p].sum);//把左边的所有贡献加起来,因为是求前缀和
}
return res;
}
int findFirst(int l, int r, i64 tar) {
return findFirst(1, 0, n, l, r, tar);
}
};
struct Info {i64 sum{}, cnt{};};
Info operator + (const Info& a, const Info& b) {return {a.sum + b.sum, a.cnt + b.cnt};}
void solve()
{
int n, Q; std::cin >> n >> Q; std::vector<int> a(n); for (auto& ai : a) {std::cin >> ai;}
//离散化正数
std::vector<int> positives; auto get_positive = [&](auto& x) {if (x > 0) {positives.push_back(x);} return ;};
for (auto& ai : a) {get_positive(ai);}
std::vector<std::pair<int, int>> querires(Q); for (auto&[x, v] : querires) {std::cin >> x >> v; --x; get_positive(v);}
Discreter discreter(positives);
//建权值线段树
SegmentTree<Info> T(n + Q); for (auto& ai : a) if (ai > 0) {T.modify(discreter.query(ai), {ai, 1});}
i64 negative_abs_sum{}; for (auto&[x, v] : querires) {
//当前这个下标上对应的数的权值线段树的值
//不一定就是单点赋值,而是把修改前的那个点减去一次a[x], 然后在新的v对应的上面加一次a=v
//修改前
if (a[x] <= 0) {negative_abs_sum -= std::abs(a[x]);} else {T.modify(discreter.query(a[x]), {-a[x], -1});}
//修改后
if (v <= 0) {negative_abs_sum += std::abs(v);} else {T.modify(discreter.query(v), {v, 1});} a[x] = v;
//第一遍线段树二分
int k{T.findFirst(0, n + Q, negative_abs_sum)};
if (k == -1) {std::cout << T.rangeQuery(0, n + Q).cnt + 1 << "\n"; continue;}
i64 pre_sum{T.rangeQuery(0, k).sum};
int k_take{}, pre_take{T.rangeQuery(0, k).cnt};
//第二遍找k取了多少个
auto k_sum{T.rangeQuery(k, k + 1).sum};
auto k_val{discreter.queryInv(k)};
k_take = (negative_abs_sum - pre_sum) / k_val + 1;
std::cout << k_take + pre_take << "\n";
}
}
signed main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int _{1};
#ifdef tests
std::cin >> _;
#endif
while(_--) solve();
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3632kb
input:
3 5 1 2 3 3 4 2 -2 1 -3 3 1 2 1
output:
1 2 2 2 3
result:
ok 5 number(s): "1 2 2 2 3"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3496kb
input:
3 5 1 2 3 3 4 2 -2 1 3 3 1 2 1
output:
1 2 1 2 1
result:
ok 5 number(s): "1 2 1 2 1"
Test #3:
score: 0
Accepted
time: 0ms
memory: 3624kb
input:
1 1 1000000000 1 1000000000
output:
1
result:
ok 1 number(s): "1"
Test #4:
score: 0
Accepted
time: 0ms
memory: 3548kb
input:
1 1 -1000000000 1 -1000000000
output:
1
result:
ok 1 number(s): "1"
Test #5:
score: 0
Accepted
time: 1ms
memory: 3724kb
input:
1000 1000 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
output:
946 65 252 410 915 592 983 487 343 899 809 432 586 587 139 464 804 84 476 699 504 149 579 352 375 856 545 166 140 657 568 509 275 710 873 430 537 879 301 1 298 970 923 510 984 642 55 879 941 344 464 788 917 994 571 610 491 442 926 101 986 840 624 613 425 345 816 423 275 221 317 113 386 116 469 260 4...
result:
ok 1000 numbers
Test #6:
score: -100
Wrong Answer
time: 1ms
memory: 3728kb
input:
1000 1000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000000 1 -1000000...
output:
352 221 133 13 137 210 141 149 25 267 242 227 295 344 13 6 58 265 85 309 340 469 20 368 336 481 402 143 389 215 458 60 481 341 390 476 118 288 262 357 488 407 243 145 495 164 34 419 92 24 327 135 176 113 144 310 100 112 314 295 26 458 151 240 314 345 376 23 22 365 78 212 134 112 123 175 204 434 415 ...
result:
wrong answer 1st numbers differ - expected: '500', found: '352'