Submission #823519

#TimeUsernameProblemLanguageResultExecution timeMemory
823519fatemetmhrComparing Plants (IOI20_plants)C++17
100 / 100
1296 ms178616 KiB
// vaghan ide i nadaram chi benevisam dige :/


#include "plants.h"
#include <bits/stdc++.h>

using namespace std;

#define all(x) x.begin(), x.end()
#define fi     first
#define se     second
#define mp     make_pair
#define pb     push_back

typedef long long ll;

const int maxn5 = 2e5 + 10;
const int maxnt = 1e6 + 10;
const int lg    = 20;
const int maxn3 = 310;
const int mod   = 1e9 + 10;

int n, ind[maxn5];
pair <int, ll> ed[2][lg][maxn5];
vector <int> av;

namespace seg3{

	pair <int, int> mn[maxnt];

	void build(int l, int r, int v){
		mn[v] = {maxn5, -1};
		if(r - l == 1)
			return;
		int mid = (l + r) >> 1;
		build(l, mid, v * 2);
		build(mid, r, v * 2 + 1);
	}

	void upd(int l, int r, int id, int val, int v){
		if(r - l == 1){
			mn[v] = {val, l};
			return;
		}
		int mid = (l + r) >> 1;
		if(id < mid)
			upd(l, mid, id, val, v * 2);
		else
			upd(mid, r, id, val, v * 2 + 1);
		mn[v] = min(mn[v * 2], mn[v * 2 + 1]);
	}

	pair <int, int> get_min(int l, int r, int lq, int rq, int v){
		if(rq <= l || r <= lq)
			return mp(maxn5, -1);
		if(lq <= l && r <= rq)
			return mn[v];
		int mid = (l + r) >> 1;
		return min(get_min(l, mid, lq, rq, v * 2), get_min(mid, r, lq, rq, v * 2 + 1));
	}
}



struct seg{

	ll lazy[maxnt];
	pair <ll, int> mn[maxnt];

	void upd(int l, int r, int id, int val, int v){
		if(r - l == 1){
			lazy[v] = 0;
			mn[v] = {val, l};
			return;
		}
		int mid = (l + r) >> 1;
		if(id < mid)
			upd(l, mid, id, val, v * 2);
		else
			upd(mid, r, id, val, v * 2 + 1);
		mn[v] = min(mn[v * 2], mn[v * 2 + 1]);
		mn[v].fi += lazy[v];
	}

	void add(int l, int r, int lq, int rq, int val, int v){
		if(rq <= l || r <= lq)
			return;
		if(lq <= l && r <= rq){
			lazy[v] += val;
			mn[v].fi += val;
			return;
		}
		int mid = (l + r) >> 1;
		add(l, mid, lq, rq, val, v * 2);
		add(mid, r, lq, rq, val, v * 2 + 1);
		mn[v] = min(mn[v * 2], mn[v * 2 + 1]);
		mn[v].fi += lazy[v];
	}
} seg1, seg2;

void init(int k, vector<int> r) {
	n = r.size();
	for(int i = 0; i < n; i++){
		seg1.upd(0, n, i, r[i], 1);
		seg2.upd(0, n, i, r[i], 1);
	}
	bool con = true;
	while(con){
		con = false;
		while(seg1.mn[1].fi == 0){
			con = true;
			int v = seg1.mn[1].se;
			//cout << "ok seg1 " << v << endl;
			seg1.upd(0, n, v, mod / 2, 1);
			if(v < n - 1)
				seg2.add(0, n, v + 1, min(n, v + k), 1, 1);
			if(v + k > n)
				seg2.add(0, n, 0, v + k - n, 1, 1);
		}
		if(seg2.mn[1].fi == 0){
			con = true;
			int v = seg2.mn[1].se;
			//cout << "ok seg2 " << v << ' ' << k << ' ' << (v - (k - 1)) << endl;
			av.pb(v);
			seg2.upd(0, n, v, mod / 2, 1);
			if(v < n - 1)
				seg2.add(0, n, v + 1, min(n, v + k), -1, 1);
			if(v + k > n)
				seg2.add(0, n, 0, v + k - n, -1, 1);
			if(v){
				seg1.add(0, n, max(0, v - (k - 1)), v, -1, 1);
				seg2.add(0, n, max(0, v - (k - 1)), v, -1, 1);
			}
			if(v - (k - 1) < 0){
				seg1.add(0, n, v - (k - 1) + n, n, -1, 1);
				seg2.add(0, n, v - (k - 1) + n, n, -1, 1);
			}
		}

	}
	//cout << av.size() << endl;
	reverse(all(av));
	for(int i = 0; i < n; i++){
		ind[av[i]] = i;
		//cout << av[i] << ' ';
	}
	//cout << endl;
	memset(ed, -1, sizeof ed);
	seg3::build(0, n, 1);
	for(int i = n - 1; i >= 0; i--){
		int v = av[i];
		pair <int, int> ans1 = {maxn5, -1}, ans2 = {maxn5, -1};
		if(v < n - 1)
			ans1 = seg3::get_min(0, n, v, min(n, v + k), 1);
		if(v + k > n)
			ans2 = seg3::get_min(0, n, 0, v + k - n, 1);
		ans1 = min(ans1, ans2);
		ed[0][0][v] = {ans1.se, (ans1.se - v + n) % n};
		ans1 = ans2 = {maxn5, -1};
		if(v)
			ans1 = seg3::get_min(0, n, max(0, v - k + 1), v, 1);
		if(v - k + 1 < 0)
			ans2 = seg3::get_min(0, n, v - k + 1 + n, n, 1);
		ans1 = min(ans1, ans2);
		ed[1][0][v] = {ans1.se, (v - ans1.se + n) % n};
		seg3::upd(0, n, v, i, 1);
	}
	for(int i = 1; i < lg; i++) for(int j = 0; j < n; j++){
		if(ed[0][i - 1][j].fi != -1)
			ed[0][i][j] = {ed[0][i - 1][ed[0][i - 1][j].fi].fi, ed[0][i - 1][ed[0][i - 1][j].fi].se + ed[0][i - 1][j].se};
		if(ed[1][i - 1][j].fi != -1)
			ed[1][i][j] = {ed[1][i - 1][ed[1][i - 1][j].fi].fi, ed[1][i - 1][ed[1][i - 1][j].fi].se + ed[1][i - 1][j].se};
	}
	return;
}

ll find_len(int x, int lim, int ty){
	ll len = 0;
	for(int i = lg - 1; i >= 0; i--)
		if(ed[ty][i][x].fi != -1 && ind[ed[ty][i][x].fi] <= lim){
			len += ed[ty][i][x].se;
			x = ed[ty][i][x].fi;
		}
	return len;
}

int compare_plants(int x, int y) {
	int sw = -1;
	if(ind[x] > ind[y]){
		swap(x, y);
		sw = 1;
	}
	ll len = find_len(x, ind[y], 0);
	if((y - x + n) % n <= len)
		return sw;
	len = find_len(x, ind[y], 1);
	if((x - y + n) % n <= len)
		return sw;
	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...