This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/**
____ ____ ____ ____ ____ ____
||l |||e |||i |||n |||a |||d ||
||__|||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|/__\|
**/
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
void speed()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
}
const int maxn = 250010;
const ll inf = 1e18;
struct node
{
ll min_val, min_lf, min_rf;
node(ll _min_val = inf, ll _min_lf = -1, ll _min_rf = -1)
{
min_val = _min_val;
min_lf = _min_lf;
min_rf = _min_rf;
}
};
node merge_nodes(node lf, node rf)
{
if (lf.min_val < rf.min_val)
return lf;
if (rf.min_val < lf.min_val)
return rf;
node cur = lf;
if (lf.min_rf == rf.min_lf - 1)
{
cur.min_rf = rf.min_rf;
}
return cur;
}
struct segment_tree
{
node tree[4 * maxn];
ll lazy[4 * maxn];
void push_lazy(int root, int left, int right)
{
tree[root].min_val += lazy[root];
if (left != right)
{
lazy[root * 2] += lazy[root];
lazy[root * 2 + 1] += lazy[root];
}
lazy[root] = 0;
}
void build(int root, int left, int right)
{
if (left == right)
{
tree[root].min_lf = left;
tree[root].min_rf = right;
tree[root].min_val = 0;
return;
}
int mid = (left + right) / 2;
build(root * 2, left, mid);
build(root * 2 + 1, mid + 1, right);
tree[root] = merge_nodes(tree[root * 2], tree[root * 2 + 1]);
}
void update(int root, int left, int right, int qleft, int qright, ll cur)
{
push_lazy(root, left, right);
if (left > qright || right < qleft)
return;
if (left >= qleft && right <= qright)
{
lazy[root] = cur;
push_lazy(root, left, right);
return;
}
int mid = (left + right) / 2;
update(root * 2, left, mid, qleft, qright, cur);
update(root * 2 + 1, mid + 1, right, qleft, qright, cur);
tree[root] = merge_nodes(tree[root * 2], tree[root * 2 + 1]);
}
node query(int root, int left, int right, int qleft, int qright)
{
push_lazy(root, left, right);
if (left > qright || right < qleft)
return node();
if (left >= qleft && right <= qright)
return tree[root];
int mid = (left + right) / 2;
return merge_nodes(query(root * 2, left, mid, qleft, qright),
query(root * 2 + 1, mid + 1, right, qleft, qright));
}
};
int n, m, q;
void input()
{
cin >> n >> m >> q;
}
struct task
{
int idx;
ll pos;
task(int _idx = 0, ll _pos = 0)
{
idx = _idx;
pos = _pos;
}
};
struct bit
{
ll fen[maxn];
void update(int pos, ll val)
{
for (int i = pos; i < maxn; i += (i & -i))
fen[i] += val;
}
ll query(int pos)
{
ll sum = 0;
for (int i = pos; i > 0; i -= (i & -i))
sum += fen[i];
return sum;
}
void range_update(int l, int r, ll v)
{
update(l, v);
update(r + 1, - v);
}
int find_kth(ll to)
{
int pos = 0;
ll sum = 0;
for (int bit = 20; bit >= 0; bit --)
{
if (pos + (1 << bit) > maxn)
continue;
ll new_sum = sum + fen[pos + (1 << bit)];
if (new_sum < to)
{
pos = pos + (1 << bit);
sum = new_sum;
}
}
return pos + 1;
}
};
vector < task > ask[maxn];
segment_tree line_tree;
bit pass_tree;
int ans[maxn];
pair < int, ll > add[maxn];
vector < int > upd[maxn];
int query_cnt = 0;
void simulate()
{
line_tree.build(1, 1, n);
int t, l, r, c, a; /// careful overflow
ll k, b;
int cnt = 0;
for (int i = 1; i <= q; i ++)
{
cin >> t;
if (t == 1)
{
cin >> l >> r >> c >> k;
line_tree.update(1, 1, n, l, r, k);
add[i] = {c, k};
upd[l].push_back(i);
upd[r + 1].push_back(-i);
}
else
if (t == 2)
{
cin >> l >> r >> k;
line_tree.update(1, 1, n, l, r, -k);
pass_tree.range_update(l, r, k);
node cur;
while(true)
{
cur = line_tree.query(1, 1, n, l, r);
if (cur.min_val >= 0)
break;
pass_tree.range_update(cur.min_lf, cur.min_rf, cur.min_val);
line_tree.update(1, 1, n, cur.min_lf, cur.min_rf, - cur.min_val);
cnt ++;
}
}
else
{
cin >> a >> b;
query_cnt ++;
if (line_tree.query(1, 1, n, a, a).min_val < b)
{
ans[query_cnt] = 0;
}
else
{
///cout << "here " << query_cnt << " " << pass_tree.query(a) << " " << line_tree.query(1, 1, n, a, a).min_val << endl;
ask[a].push_back(task(query_cnt, pass_tree.query(a) + b));
}
}
}
assert(cnt <= 2 * n);
}
bit active;
void answer_tasks()
{
for (int i = 1; i <= n; i ++)
{
for (int cur : upd[i])
{
if (cur > 0)
{
active.update(cur, add[cur].second);
}
else
{
active.update(-cur, - add[-cur].second);
}
}
for (task cur : ask[i])
{
ans[cur.idx] = add[active.find_kth(cur.pos)].first;
///cout << cur.idx << " : " << cur.shop << " " << cur.pos << endl;
}
}
for (int i = 1; i <= query_cnt; i ++)
{
cout << ans[i] << endl;
}
}
void solve()
{
input();
simulate();
answer_tasks();
}
int main()
{
speed();
solve();
return 0;
}
# | 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... |