Submission #1363756

#TimeUsernameProblemLanguageResultExecution timeMemory
1363756retardeComparing Plants (IOI20_plants)C++20
44 / 100
251 ms28980 KiB
#include "plants.h"
#include <bits/stdc++.h>
using namespace std;

int n;

struct gap {
	int i, j; // gap from i -> j
	bool operator<(const gap &other) const {
		return (j - i) < (other.j - other.i);
	};
	int eval() {return j - i;}
};

struct node {
	int mn, l, r; gap gp;
};

node merge(node &a, node &b) {
	if (a.mn < b.mn) return a;
	else if (a.mn > b.mn) return b;
	return {a.mn, a.l, b.r, max({a.gp, b.gp, {a.r, b.l}})};
}

struct segtree {
    private:
    vector<node> seg, a;
	vector<int> lazy;
    int n;

    public:
    segtree(vector<int> &x) {
        n = (int)x.size();
        seg.resize(4 * n);
        lazy.resize(4 * n);
		a.resize(n);
		gap inf = {(int)1e9, (int)-1e9};
        for (int i = 0; i < n; i++) a[i] = {x[i], i, i, inf};
        build(1, 0, n - 1);
    }
    void build(int i, int l, int r) {
        if (l == r) {
            seg[i] = a[l];
            return;
        }
        int mid = (l + r) / 2;
        build(i * 2, l, mid);
        build(i * 2 + 1, mid + 1, r);
        seg[i] = merge(seg[i * 2], seg[i * 2 + 1]);
    }
    void push(int i, int l, int r) {
        seg[i].mn += lazy[i];
        if (l == r) {
            lazy[i] = 0;
            return;
        }
        lazy[i * 2] += lazy[i];
        lazy[i * 2 + 1] += lazy[i];
        lazy[i] = 0;
    }
    node query(int i, int l, int r, int ql, int qr) {
        push(i, l, r);
        if (r < ql || qr < l) {
			gap inf2 = {(int)1e9, (int)-1e9};
			node bruh = {(int)1e9, (int)1e9, (int)1e9, inf2};
			return bruh;
		}
        if (ql <= l && r <= qr) return seg[i];
        int mid = (l + r) / 2;
		node lft = query(i * 2, l, mid, ql, qr);
		node rgt = query(i * 2 + 1, mid + 1, r, ql, qr);
        return merge(lft, rgt);
    }
    void upd(int i, int l, int r, int ql, int qr, int qv) {
        push(i, l, r);
        if (r < ql || qr < l) return;
        if (ql <= l && r <= qr) {
            lazy[i] += qv;
            push(i, l, r);
            return;
        }
        int mid = (l + r) / 2;
        upd(i * 2, l, mid, ql, qr, qv);
        upd(i * 2 + 1, mid + 1, r, ql, qr, qv);
		seg[i] = merge(seg[i * 2], seg[i * 2 + 1]);
    }

    void build() {
        build(1, 0, n - 1);
    }
    node query(int ql, int qr) {
        return query(1, 0, n - 1, ql, qr);
    }
    void upd(int ql, int qr, int qv) {
		if (ql > qr) return;
        upd(1, 0, n - 1, ql, qr, qv);
    }
};

// vector<int> getmins(segtree &st) {
// 	pair<int, int> ogmn = st.query(0, n - 1);
// 	vector<int> ans;
// 	while (st.query(0, n - 1).first == ogmn.first) {
// 		pair<int, int> cur = st.query(0, n - 1);
// 		ans.push_back(cur.second);
// 		st.upd(cur.second, cur.second, 2e9);
// 	}
// 	for (auto &x : ans) st.upd(x, x, -2e9);
// 	return ans;
// }

vector<int> inds;
void init(int k, vector<int> r) {
	n = (int)r.size(); inds.resize(n);
	segtree st(r); vector<int> order; // descending
	for (int _ = 0; _ < n; _++) {
		// vector<int> poss = getmins(st);

		// // cout << "mins:\n";
		// // for (auto &x : poss) cout << x << " ";
		// // cout << '\n';

		// assert((int)poss.size() <= 2);

		// int pos = -1;
		// for (int i = 0; i < (int)poss.size(); i++) {
		// 	int prev = (i + (int)poss.size() - 1) % ((int)poss.size());
		// 	if (poss[i] > poss[prev]) {
		// 		if (poss[i] >= poss[prev] + k) {
		// 			pos = poss[i];
		// 			break;
		// 		}
		// 	} else {
		// 		int y = (poss[prev] + k);
		// 		if (y < n) {
		// 			pos = poss[i];
		// 			break;
		// 		}
		// 		y %= n;
		// 		if (poss[i] >= y) {
		// 			pos = poss[i];
		// 			break;
		// 		}
		// 	}
		// }

		// if ((int)poss.size() == 1) pos = poss[0];

		int pos = -1;
		node nd = st.query(0, n - 1);
		if (nd.gp.eval() >= k) {
			pos = nd.gp.j;
		} else {
			pos = nd.l;
		}

		if (pos == -1) break;
		assert(pos != -1);
		order.push_back(pos);
		st.upd(pos, pos, (int)2e9);

		// remove previous k
		if (pos - k + 1 >= 0) {
			st.upd(pos - k + 1, pos - 1, -1);
		} else {
			st.upd(0, pos - 1, -1);
			int back = (pos - k + 1 + n) % n;
			st.upd(back, n - 1, -1);
		}
	}

	// cout << "order:\n";
	// for (auto &x : order) cout << x << " ";
	// cout << '\n';

	for (int i = 0; i < n; i++) inds[order[i]] = i;
}

int compare_plants(int x, int y) {
	if (inds[x] < inds[y]) return 1;
	else return -1;
	// cout << "query" << mat[x][y] << " " << mat[y][x] << '\n';
	// if (!mat[x][y] && !mat[y][x]) return 0;
	// if (mat[x][y]) return 1;
	// else return -1;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...