結果
| 問題 |
No.924 紲星
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2019-09-05 23:50:36 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 5,702 bytes |
| コンパイル時間 | 2,304 ms |
| コンパイル使用メモリ | 189,948 KB |
| 実行使用メモリ | 20,644 KB |
| 最終ジャッジ日時 | 2024-09-15 05:28:23 |
| 合計ジャッジ時間 | 21,645 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 8 RE * 6 TLE * 1 -- * 1 |
ソースコード
#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = long long;
using std::cout;
using std::endl;
using std::cin;
template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename Monoid>
class segment_tree {
using value_type = Monoid;
using size_type = size_t;
using binary_function = std::function<value_type(value_type, value_type)>;
using checker = std::function<bool(value_type)>;
const size_type size_;
size_type height_;
const value_type id;
const binary_function bi_func;
std::vector<value_type> data;
private:
const size_type get_height(const size_type& size) const {
size_type height = 1;
while(1 << height < size) height++;
return height;
}
const size_type base_size() const {
return 1 << height_;
}
void meld(const size_type& index) {
data[index] = bi_func(data[index << 1 ^ 0], data[index << 1 ^ 1]);
}
public:
segment_tree(const size_type& size, const binary_function& bi_func, const value_type& id)
: size_(size),
bi_func(bi_func),
id(id) {
height_ = get_height(size);
data.assign(base_size() << 1, id);
}
value_type fold(size_type left, size_type right) {
value_type l_value = id,
r_value = id;
for(left += base_size(), right += base_size();
left < right;
left >>= 1, right >>= 1) {
if(left & 1) l_value = bi_func(l_value, data[left++]);
if(right & 1) r_value = bi_func(data[--right], r_value);
}
return bi_func(std::move(l_value), std::move(r_value));
}
void update(size_type index, const value_type& value) {
index += base_size();
data[index] = bi_func(data[index], value);
while(index >>= 1) meld(index);
}
void change(size_type index, const value_type& value) {
index += base_size();
data[index] = value;
while(index >>= 1) meld(index);
}
const size_type search(const size_type & left, const checker & check) {
value_type val = id;
size_t base_size_ = base_size();
auto find = [&](auto&& find, size_type k, size_type l, size_type r) -> int {
if(l + 1 == r) {
val = bi_func(val, data[k]);
return (check(val) ? k - base_size_ : -1);
}
const size_type mid = (l + r) >> 1;
if(mid <= left) return find(find, k << 1 ^ 1, mid, r);
if(left <= l and !check(bi_func(val, data[k]))) {
val = bi_func(val, data[k]);
return -1;
}
const int left_ret = find(find, k << 1 ^ 0, l, mid);
if(left_ret == -1) return find(find, k << 1 ^ 1, mid, r);
return left_ret;
};
return find(find, 1, 0, base_size_);
}
value_type operator[](const size_type& index) const {
return data[index + base_size()];
}
const size_type size() const {
return size_;
}
const bool empty() const {
return data.empty();
}
};
class Mo {
// segment: [left, right)
class Query {
public:
int left;
int right;
int id;
Query(const int left, const int right, const int id)
: left(left), right(right), id(id) {};
};
std::vector<Query> queries;
const size_t N;
size_t getSqrt(const size_t t) {
size_t sqrt = 0;
while(sqrt * sqrt <= t) sqrt++;
return sqrt - 1;
}
void build(const size_t sqrtQ) {
sort(begin(queries), end(queries), [&](Query a, Query b) {
const int bucketA = a.left / sqrtQ, bucketB = b.left / sqrtQ;
if(bucketA == bucketB) {
if(bucketA & 1) return a.right > b.right;
return a.right < b.right;
}
return bucketA < bucketB;
});
}
public:
Mo(size_t n) : N(n) {}
inline void addQuery(int left, int right) {
queries.push_back(Query(left, right, (int)queries.size()));
}
inline int process() {
static int left = 0, right = 0, index = 0;
if(!index) build(getSqrt(queries.size()));
Query q = queries[index++];
while(left > q.left) add(--left);
while(left < q.left) del(left++);
while(right < q.right) add(right++);
while(right > q.right) del(--right);
return q.id;
}
inline void add(int i);
inline void del(int i);
};
segment_tree<std::pair<i64, int>> seg(1e5, [](auto x, auto y) { return std::pair<i64, int>{x.first + y.first, x.second + y.second}; }, {0, 0});
std::vector<int> latte, malta, a;
// :::impl:::
inline void Mo::add(int i) {
int k = malta[i];
seg.update(k, {a[i], 1});
};
inline void Mo::del(int i) {
int k = malta[i];
seg.update(k, {-a[i], -1});
};
int main() {
// input
int n, q; scanf("%d%d", &n, &q);
assert(1 <= n and n <= 2e5);
assert(1 <= q and q <= 2e5);
a.resize(n);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
assert(-1e9 <= a[i] and a[i] <= 1e9);
}
std::vector<int> L(q), R(q);
for(int i = 0; i < q; i++) {
scanf("%d%d", &L[i], &R[i]);
assert(1 <= L[i] and L[i] <= n);
assert(1 <= R[i] and R[i] <= n);
assert(L[i] <= R[i]);
L[i]--;
}
// solve
latte = a;
malta.resize(n);
sort(begin(latte), end(latte));
latte.erase(unique(begin(latte), end(latte)), end(latte));
for(int i = 0; i < n; i++) malta[i] = lower_bound(begin(latte), end(latte), a[i]) - begin(latte);
Mo mo(n);
for(int i = 0; i < q; i++) mo.addQuery(L[i], R[i]);
std::vector<i64> ans(q, -1);
std::vector<i64> cen(q, -1);
while(q--) {
int id = mo.process();
const int len = (R[id] - L[id]) >> 1;
auto check = [len](std::pair<i64, int> p) { return p.second > len; };
const int center = seg.search(0, check);
const i64 val = latte[center];
auto left = seg.fold(0, center);
auto right = seg.fold(center, n);
i64 A = val * left.second - left.first;
i64 B = right.first - val * right.second;
ans[id] = A + B;
}
for(int i = 0; i < ans.size(); i++) {
printf("%lld\n", ans[i]);
}
return 0;
}