Submission #589764

#TimeUsernameProblemLanguageResultExecution timeMemory
589764LucppComparing Plants (IOI20_plants)C++17
100 / 100
1809 ms97056 KiB
#include "plants.h"
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e8;
const int LOG = 18;
int n, k, cap;
vector<vector<int>> jumpL, jumpR;
vector<int> h;

struct Data{
	int m = INF, l, r, ind = -1;
};
Data combine(Data a, Data b){
	Data d;
	d.m = min(a.m, b.m);
	if(d.m == a.m) d.l = a.l;
	else d.l = b.l;
	if(d.m == b.m) d.r = b.r;
	else d.r = a.r;
	if(d.m == a.m && a.ind != -1) d.ind = a.ind;
	if(d.m == b.m && b.ind != -1) d.ind = b.ind;
	if(d.m == a.m && d.m == b.m && b.l-a.r >= k) d.ind = b.l;
	return d;
}
vector<Data> S;
vector<int> O;
vector<bool> lazy;
void build(vector<int> v){
	for(cap = 1; cap < (int)v.size(); cap *= 2);
	S.resize(2*cap);
	O.resize(2*cap);
	lazy.resize(2*cap);
	for(int i = 0; i < (int)v.size(); i++) S[i+cap] = Data{v[i], i+1, i+1};
	for(int i = cap-1; i > 0; i--) S[i] = combine(S[2*i], S[2*i+1]);
}
void apply(int v, int i){
	lazy[i] = true;
	O[i] += v;
	S[i].m += v;
}
void push(int i){
	if(lazy[i]){
		apply(O[i], 2*i);
		apply(O[i], 2*i+1);
		O[i] = 0;
		lazy[i] = false;
	}
}
void upd(int p, int v, int a, int b, int i){
	if(a == b) S[i] = {v, p, p, -1};
	else{
		push(i);
		int m = (a+b)/2;
		if(p <= m) upd(p, v, a, m, 2*i);
		else upd(p, v, m+1, b, 2*i+1);
		S[i] = combine(S[2*i], S[2*i+1]);
	}
}
void apply(int l, int r, int v, int a, int b, int i){
	if(l <= a && b <= r) apply(v, i);
	else if(b < l || r < a) return;
	else{
		push(i);
		int m = (a+b)/2;
		apply(l, r, v, a, m, 2*i);
		apply(l, r, v, m+1, b, 2*i+1);
		S[i] = combine(S[2*i], S[2*i+1]);
	}
}

vector<pair<int, int>> S2;
void build2(){
	S2.resize(2*cap, {INF, 0});
	for(int i = cap; i < 2*cap; i++) S2[i].second = i-cap;
}
void upd2(int i, int v){
	i += cap;
	S2[i].first = v;
	while(i > 1){
		i /= 2;
		S2[i] = min(S2[2*i], S2[2*i+1]);
	}
}
pair<int, int> qry2(int l, int r, int a, int b, int i){
	if(l <= a && b <= r) return S2[i];
	if(b < l || r < a) return {INF, 0};
	int m = (a+b)/2;
	return min(qry2(l, r, a, m, 2*i), qry2(l, r, m+1, b, 2*i+1));
}


bool findR(int a, int b){
	for(int i = LOG-1; i >= 0; i--){
		if(jumpR[i][a] == -1) continue;
		if(jumpR[i][a] <= b) a = jumpR[i][a];
	}
	return b-a<k && h[a] <= h[b];
}
bool findL(int a, int b){
	for(int i = LOG-1; i >= 0; i--){
		if(jumpL[i][a] == -1) continue;
		if(jumpL[i][a] >= b) a = jumpL[i][a];
	}
	return a-b<k && h[a] <= h[b];
}

void init(int K, vector<int> r) {
	k = K;
	n = (int)r.size();
	h.resize(2*n);
	r.resize(2*n);
	jumpL.assign(LOG, vector<int>(2*n, -1));
	jumpR.assign(LOG, vector<int>(2*n, -1));
	for(int i = 0; i < n; i++) r[i+n] = r[i];
	build(r);
	build2();
	for(int it = 0; it < n; it++){
		assert(S[1].m == 0);
		assert(S[1].ind != -1);
		int i = S[1].ind;
		i = (i-1)%n;
		h[i] = h[i+n] = n-it;
		upd2(i, h[i]);
		upd2(i+n, h[i]);

		auto p = qry2(i+2, i+k, 1, cap, 1);
		if(p.first != INF) jumpR[0][i] = p.second;
		p = qry2(i+n+2, i+n+k, 1, cap, 1);
		if(p.first != INF) jumpR[0][i+n] = p.second;
		p = qry2(i-k+2, i, 1, cap, 1);
		if(p.first != INF) jumpL[0][i] = p.second;
		p = qry2(i+n-k+2, i+n, 1, cap, 1);
		if(p.first != INF) jumpL[0][i+n] = p.second;

		upd(i+1, INF, 1, cap, 1);
		upd(i+n+1, INF, 1, cap, 1);
		apply(max(0, i-k+1)+1, i, -1, 1, cap, 1);
		apply(i+n-k+2, i+n, -1, 1, cap, 1);
		apply(i+2*n-k+2, 2*n, -1, 1, cap, 1);

	}
	for(int i = 1; i < LOG; i++){
		for(int j = 0; j < 2*n; j++){
			if(jumpR[i-1][j] != -1) jumpR[i][j] = jumpR[i-1][jumpR[i-1][j]];
			if(jumpL[i-1][j] != -1) jumpL[i][j] = jumpL[i-1][jumpL[i-1][j]];
		}
	}
	
}

int compare_plants(int x, int y) {
	if(h[x] < h[y]){
		if(findR(x, y) || findL(x+n, y)) return -1;
		else return 0;
	}
	else{
		if(findR(y, x+n) || findL(y, x)) return 1;
		else 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...