답안 #936354

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
936354 2024-03-01T17:02:27 Z EJIC_B_KEDAX 식물 비교 (IOI20_plants) C++17
19 / 100
4000 ms 148068 KB
#include <bits/stdc++.h>
#include "plants.h"

#define x first
#define y second

using ll = long long;
 
using namespace std;
 
const int LG = 18, N = 1 << LG;
int st1[2 * N], st2[2 * N], lz1[2 * N], lz2[2 * N], timer = 1, fndl[2 * N], used3[N], level[N], kk, nn;
pair<int, int> fnd[2 * N], binupl[LG][N], binupr[LG][N];
vector<pair<int, int>> mst[2 * N];

void push(int i, int st[], int lz[]) {
	if (lz[i] != -1) {
		st[2 * i + 1] = lz[i];
		st[2 * i + 2] = lz[i];
		lz[2 * i + 1] = lz[i];
		lz[2 * i + 2] = lz[i];
		lz[i] = -1;
	}
}

void set_seg(int l, int r, int x, int st[], int lz[], int l1 = 0, int r1 = N - 1, int i = 0) {
	if (l1 >= l && r1 <= r) {
		st[i] = x;
		lz[i] = x;
		return;
	}
	if (l1 > r || r1 < l) {
		return;
	}
	push(i, st, lz);
	set_seg(l, r, x, st, lz, l1, (l1 + r1) / 2, 2 * i + 1);
	set_seg(l, r, x, st, lz, (l1 + r1) / 2 + 1, r1, 2 * i + 2);
	st[i] = min(st[2 * i + 1], st[2 * i + 2]);
}

int get(int ind, int st[], int lz[], int l1 = 0, int r1 = N - 1, int i = 0) {
	if (l1 == ind && r1 == ind) {
		return st[i];
	}
	if (l1 > ind || r1 < ind) {
		return INT32_MAX;
	}
	push(i, st, lz);
	return min(get(ind, st, lz, l1, (l1 + r1) / 2, 2 * i + 1), get(ind, st, lz, (l1 + r1) / 2 + 1, r1, 2 * i + 2));
}

void push(int i) {
	fnd[2 * i + 1].x += fndl[i];
	fnd[2 * i + 2].x += fndl[i];
	fndl[2 * i + 1] += fndl[i];
	fndl[2 * i + 2] += fndl[i];
	fndl[i] = 0;
}

void add_seg(int l, int r, int x, int l1 = 0, int r1 = N - 1, int i = 0) {
	if (l1 >= l && r1 <= r) {
		fnd[i].x += x;
		fndl[i] += x;
		return;
	}
	if (l1 > r || r1 < l) {
		return;
	}
	push(i);
	add_seg(l, r, x, l1, (l1 + r1) / 2, 2 * i + 1);
	add_seg(l, r, x, (l1 + r1) / 2 + 1, r1, 2 * i + 2);
	fnd[i] = min(fnd[2 * i + 1], fnd[2 * i + 2]);
}

pair<int, int> get_min(int l, int r, int l1 = 0, int r1 = N - 1, int i = 0) {
	if (l1 >= l && r1 <= r) {
		return fnd[i];
	}
	if (l1 > r || r1 < l) {
		return {INT32_MAX, -1};
	}
	push(i);
	return min(get_min(l, r, l1, (l1 + r1) / 2, 2 * i + 1), get_min(l, r, (l1 + r1) / 2 + 1, r1, 2 * i + 2));
}

pair<int, int> find_max(int i, int v) {
	int l = -1, r = mst[i].size();
	while (r - l > 1) {
		int m = (r + l) / 2;
		if (mst[i][m].x >= v) {
			r = m;
		} else {
			l = m;
		}
	}
	return l == -1 ? make_pair(-1, N) : mst[i][l];
}

pair<int, int> get_max(int l, int r, int v) {
	l += N - 1;
	r += N - 1;
	pair<int, int> res = {-1, -1};
	while (l <= r) {
		if (~l & 1) {
			res = max(res, find_max(l++, v));
		}
		if (r & 1) {
			res = max(res, find_max(r--, v));
		}
		l = (l - 1) / 2;
		r = (r - 1) / 2;
	}
	return res;
}

void mrg(int to, int a, int b) {
	mst[to].resize(mst[a].size() + mst[b].size());
	std::merge(mst[a].begin(), mst[a].end(), mst[b].begin(), mst[b].end(), mst[to].begin());
}

void init(int k, vector<int> r) {
	kk = k;
    int n = r.size();
    nn = n;
    int ok = 0;
    for (int i = 0; i < 2 * N; i++) {
    	st1[i] = -1;
    	st2[i] = -1;
    	lz1[i] = -1;
    	lz2[i] = -1;
    }
    for (int i = 0; i < N; i++) {
    	fnd[i + N - 1].y = i;
    	level[i] = n;
    }
    for (int i = 0; i < n; i++) {
    	add_seg(i, i, r[i]);
		if (r[i] == 0) {
			used3[i] = 1;
			if (i + k > n) {
				add_seg(i + 1, n - 1, 1);
				add_seg(0, i + k - n - 1, 1);
			} else {
				add_seg(i + 1, i + k - 1, 1);
			}
		}
    }
    while (ok < n) {
    	auto [value, i] = get_min(0, n - 1);
    	// if (value) {
    	// 	cout << value << ' ' << i << ' ' << ok << '\n';
    	// 	exit(1);
    	// }
    	int tmp1 = get(i, st1, lz1), tmp2 = get(i, st2, lz2);
    	if (tmp1 != -1) {
    		level[i] = min(level[i], level[tmp1] - 1);
    	}
    	if (tmp2 != -1) {
    		level[i] = min(level[i], level[tmp2] - 1);
    	}
    	vector<int> z;
        if (i + k - 1 < n) {
    		set_seg(i + 1, i + k - 1, i, st2, lz2);
    		add_seg(i + 1, i + k - 1, -1);
    	} else {
    		set_seg(i + 1, n - 1, i, st2, lz2);
    		set_seg(0, i + k - 1 - n, i, st2, lz2);
    		add_seg(i + 1, n - 1, -1);
    		add_seg(0, i + k - 1 - n, -1);
    	}
    	if (i >= k - 1) {
    		add_seg(i - k + 1, i - 1, -1);
    		int left = i - k + 1;
    		while (left <= i - 1 && !get_min(left, i - 1).x) {
    			z.push_back(get_min(left, i - 1).y);
    			assert(left <= z.back());
    			left = z.back() + 1;
    		}
    		set_seg(i - k + 1, i - 1, i, st1, lz1);
    	} else {
    		add_seg(0, i - 1, -1);
    		set_seg(0, i - 1, i, st1, lz1);
    		add_seg(n + 1 - k + i, n - 1, -1);
    		set_seg(n + 1 - k + i, n - 1, i, st1, lz1);
    		int left = 0;
    		while (left <= i - 1 && !get_min(left, i - 1).x) {
    			z.push_back(get_min(left, i - 1).y);
    			assert(left <= z.back());
    			left = z.back() + 1;
    		}
    		left = n + 1 - k + i;
    		while (left <= n - 1 && !get_min(left, n - 1).x) {
    			z.push_back(get_min(left, n - 1).y);
    			assert(left <= z.back());
    			left = z.back() + 1;
    		}
    	}
    	if (i + k - 1 < n) {
    		int left = i + 1;
    		while (left <= i + k - 1 && !get_min(left, i + k - 1).x) {
    			z.push_back(get_min(left, i + k - 1).y);
    			assert(left <= z.back());
    			left = z.back() + 1;
    		}
    	} else {
    		int left = i + 1;
    		while (left <= n - 1 && !get_min(left, n - 1).x) {
    			z.push_back(get_min(left, n - 1).y);
    			assert(left <= z.back());
    			left = z.back() + 1;
    		}
    		left = 0;
    		while (left <= i + k - 1 - n && !get_min(left, i + k - 1 - n).x) {
    			z.push_back(get_min(left, i + k - 1 - n).y);
    			assert(left <= z.back());
    			left = z.back() + 1;
    		}
    	}
    	for (int j : z) {
    		if (!used3[j]) {
				if (j + k > n) {
					add_seg(j + 1, n - 1, 1);
					add_seg(0, j + k - n - 1, 1);
				} else {
					add_seg(j + 1, j + k - 1, 1);
				}
				used3[j] = 1;
			}
		}
        add_seg(i, i, INT32_MAX / 2);
    	ok++;
    }
    for (int i = 0; i < n; i++) {
    	mst[N - 1 + i].emplace_back(level[i], i);
    }
    for (int i = N - 2; i >= 0; i--) {
    	mrg(i, 2 * i + 1, 2 * i + 2);
    }
    for (int i = 0; i < n; i++) {
    	if (i >= k - 1) {
    		binupl[0][i].x = get_max(i - k + 1, i - 1, level[i]).y;
    	} else {
    		binupl[0][i].x = max(get_max(0, i - 1, level[i]), get_max(n + i - k + 1, n - 1, level[i])).y;
    	}
    	if (binupl[0][i].x == N) {
    		binupl[0][i].x = i;
    	}
    	binupl[0][i].y = i - binupl[0][i].x;
    	if (binupl[0][i].y < 0) {
    		binupl[0][i].y += n;
    	}
    	if (i + k - 1 < n) {
    		binupr[0][i].x = get_max(i + 1, i + k - 1, level[i]).y;
    	} else {
    		binupr[0][i].x = max(get_max(i + 1, n - 1, level[i]), get_max(0, i + k - 1 - n, level[i])).y;
    	}
    	if (binupr[0][i].x == N) {
    		binupr[0][i].x = i;
    	}
    	binupr[0][i].y = binupr[0][i].x - i;
    	if (binupr[0][i].y < 0) {
    		binupr[0][i].y += n;
    	}
    }
    for (int l = 1; l < LG; l++) {
    	for (int i = 0; i < n; i++) {
    		binupl[l][i].x = binupl[l - 1][binupl[l - 1][i].x].x;
    		binupr[l][i].x = binupr[l - 1][binupr[l - 1][i].x].x;
    		binupl[l][i].y = binupl[l - 1][binupl[l - 1][i].x].y + binupl[l - 1][i].y;
    		binupr[l][i].y = binupr[l - 1][binupr[l - 1][i].x].y + binupr[l - 1][i].y;
    	}
    }
    // for (int i = 0; i < n; i++) {
    // 	cout << level[i] << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupl[0][i].x << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupr[0][i].x << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupl[1][i].x << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupr[1][i].x << ' ';
    // }
    // cout << '\n';
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupl[0][i].y << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupr[0][i].y << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupl[1][i].y << ' ';
    // }
    // cout << '\n';
    // for (int i = 0; i < n; i++) {
    // 	cout << binupr[1][i].y << ' ';
    // }
    // cout << '\n';
}

bool try_compare(int x, int y) {
	int dist = x - y, nw = x;
	if (dist < 0) {
		dist += nn;
	}
	dist -= kk - 1;
	if (level[nw] > level[y] && dist <= 0) {
		// cout << "! " << nw << '\n';
		return true;
	}
	for (int i = LG - 1; i >= 0; i--) {
		if (binupl[i][nw].y < dist) {
			dist -= binupl[i][nw].y;
			nw = binupl[i][nw].x;
		}
	}
	dist -= binupl[0][nw].y;
	nw = binupl[0][nw].x;
	if (level[nw] > level[y] && dist <= 0) {
		// cout << "!! " << nw << '\n';
		return true;
	}
	dist = y - x, nw = x;
	if (dist < 0) {
		dist += nn;
	}
	dist -= kk - 1;
	if (level[nw] > level[y] && dist <= 0) {
		// cout << "!!! " << nw << '\n';
		return true;
	}
	for (int i = LG - 1; i >= 0; i--) {
		if (binupr[i][nw].y < dist) {
			dist -= binupr[i][nw].y;
			nw = binupr[i][nw].x;
		}
	}
	dist -= binupr[0][nw].y;
	nw = binupr[0][nw].x;
	if (level[nw] > level[y] && dist <= 0) {
		// cout << "!!!! " << nw << '\n';
		return true;
	}
	return false;
}
 
int compare_plants(int x, int y) {
	if (try_compare(x, y) && level[x] > level[y]) {
		return 1;
	}
	if (try_compare(y, x) && level[y] > level[x]) {
		return -1;
	}
	return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 102900 KB Output is correct
2 Correct 16 ms 103020 KB Output is correct
3 Correct 16 ms 103004 KB Output is correct
4 Correct 17 ms 102892 KB Output is correct
5 Correct 15 ms 103004 KB Output is correct
6 Correct 362 ms 106608 KB Output is correct
7 Correct 437 ms 111696 KB Output is correct
8 Correct 1452 ms 147492 KB Output is correct
9 Correct 1386 ms 147412 KB Output is correct
10 Correct 1281 ms 147536 KB Output is correct
11 Correct 1261 ms 147352 KB Output is correct
12 Correct 1250 ms 147356 KB Output is correct
13 Correct 1119 ms 147356 KB Output is correct
14 Correct 1279 ms 147352 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 103000 KB Output is correct
2 Correct 15 ms 103004 KB Output is correct
3 Correct 16 ms 102980 KB Output is correct
4 Correct 18 ms 103000 KB Output is correct
5 Correct 16 ms 103004 KB Output is correct
6 Correct 26 ms 103260 KB Output is correct
7 Correct 185 ms 108704 KB Output is correct
8 Correct 19 ms 103004 KB Output is correct
9 Correct 25 ms 103192 KB Output is correct
10 Correct 180 ms 108624 KB Output is correct
11 Correct 108 ms 108440 KB Output is correct
12 Correct 197 ms 108752 KB Output is correct
13 Correct 151 ms 108500 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 103000 KB Output is correct
2 Correct 15 ms 103004 KB Output is correct
3 Correct 16 ms 102980 KB Output is correct
4 Correct 18 ms 103000 KB Output is correct
5 Correct 16 ms 103004 KB Output is correct
6 Correct 26 ms 103260 KB Output is correct
7 Correct 185 ms 108704 KB Output is correct
8 Correct 19 ms 103004 KB Output is correct
9 Correct 25 ms 103192 KB Output is correct
10 Correct 180 ms 108624 KB Output is correct
11 Correct 108 ms 108440 KB Output is correct
12 Correct 197 ms 108752 KB Output is correct
13 Correct 151 ms 108500 KB Output is correct
14 Correct 339 ms 111788 KB Output is correct
15 Correct 2327 ms 148048 KB Output is correct
16 Correct 320 ms 111952 KB Output is correct
17 Correct 2375 ms 148060 KB Output is correct
18 Correct 1553 ms 147684 KB Output is correct
19 Correct 1705 ms 148068 KB Output is correct
20 Execution timed out 4100 ms 82484 KB Time limit exceeded
21 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 103000 KB Output is correct
2 Correct 15 ms 103004 KB Output is correct
3 Incorrect 132 ms 107860 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 103000 KB Output is correct
2 Correct 15 ms 103004 KB Output is correct
3 Correct 16 ms 103004 KB Output is correct
4 Correct 16 ms 103004 KB Output is correct
5 Incorrect 16 ms 103004 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 16 ms 103004 KB Output is correct
2 Correct 16 ms 103004 KB Output is correct
3 Correct 16 ms 103004 KB Output is correct
4 Correct 16 ms 103004 KB Output is correct
5 Incorrect 21 ms 103004 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 102900 KB Output is correct
2 Correct 16 ms 103020 KB Output is correct
3 Correct 16 ms 103004 KB Output is correct
4 Correct 17 ms 102892 KB Output is correct
5 Correct 15 ms 103004 KB Output is correct
6 Correct 362 ms 106608 KB Output is correct
7 Correct 437 ms 111696 KB Output is correct
8 Correct 1452 ms 147492 KB Output is correct
9 Correct 1386 ms 147412 KB Output is correct
10 Correct 1281 ms 147536 KB Output is correct
11 Correct 1261 ms 147352 KB Output is correct
12 Correct 1250 ms 147356 KB Output is correct
13 Correct 1119 ms 147356 KB Output is correct
14 Correct 1279 ms 147352 KB Output is correct
15 Correct 16 ms 103000 KB Output is correct
16 Correct 15 ms 103004 KB Output is correct
17 Correct 16 ms 102980 KB Output is correct
18 Correct 18 ms 103000 KB Output is correct
19 Correct 16 ms 103004 KB Output is correct
20 Correct 26 ms 103260 KB Output is correct
21 Correct 185 ms 108704 KB Output is correct
22 Correct 19 ms 103004 KB Output is correct
23 Correct 25 ms 103192 KB Output is correct
24 Correct 180 ms 108624 KB Output is correct
25 Correct 108 ms 108440 KB Output is correct
26 Correct 197 ms 108752 KB Output is correct
27 Correct 151 ms 108500 KB Output is correct
28 Correct 339 ms 111788 KB Output is correct
29 Correct 2327 ms 148048 KB Output is correct
30 Correct 320 ms 111952 KB Output is correct
31 Correct 2375 ms 148060 KB Output is correct
32 Correct 1553 ms 147684 KB Output is correct
33 Correct 1705 ms 148068 KB Output is correct
34 Execution timed out 4100 ms 82484 KB Time limit exceeded
35 Halted 0 ms 0 KB -