Submission #852625

#TimeUsernameProblemLanguageResultExecution timeMemory
852625danikoynovFood Court (JOI21_foodcourt)C++14
42 / 100
1033 ms52228 KiB
/**
 ____ ____ ____ ____ ____ ____
||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;
    int min_lf, min_rf;

    node(ll  _min_val = inf, int _min_lf = -1, int _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];
    int tag[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];
            tag[root * 2] = tag[root * 2 + 1] = 1;
        }
        tag[root] = 0;
        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)
    {
        if (tag[root])
        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)
    {
        if (tag[root])
        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 readInt () {
	bool minus = false;
	int result = 0;
	char ch;
	ch = getchar();
	while (true) {
		if (ch == '-') break;
		if (ch >= '0' && ch <= '9') break;
		ch = getchar();
	}
	if (ch == '-') minus = true; else result = ch-'0';
	while (true) {
		ch = getchar();
		if (ch < '0' || ch > '9') break;
		result = result*10 + (ch - '0');
	}
	if (minus)
		return -result;
	else
		return result;
}


long long int read_int(){
	char r;
	bool start=false,neg=false;
	long long int ret=0;
	while(true){
		r=getchar();
		if((r-'0'<0 || r-'0'>9) && r!='-' && !start){
			continue;
		}
		if((r-'0'<0 || r-'0'>9) && r!='-' && start){
			break;
		}
		if(start)ret*=10;
		start=true;
		if(r=='-')neg=true;
		else ret+=r-'0';
	}
	if(!neg)
		return ret;
	else
		return -ret;
}

int n, m, q;
void input()
{
    n = readInt();
    m = readInt();
    q = readInt();
    //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;
        t = readInt();
        if (t == 1)
        {
            ///cin >> l >> r >> c >> k;
            l = readInt();
            r = readInt();
            c = readInt();
            k = read_int();
            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;
                        l = readInt();
            r = readInt();
            k = read_int();
            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;
            a = readInt();
            b = read_int();
            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 <= 4 * q);

}

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()
{
    ///freopen("test.txt", "r", stdin);
    speed();
    solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...