제출 #48083

#제출 시각아이디문제언어결과실행 시간메모리
48083cheater2k팀들 (IOI15_teams)C++17
0 / 100
1141 ms433912 KiB
#include "teams.h"
#include <bits/stdc++.h>
using namespace std;

const int N = 500005;

int n;
int cntRig[N];
vector <int> lef[N];
int ver[N];

#define mid ((l + r) >> 1)
struct PersistentIT {
	int T[N * 30], L[N * 30], R[N * 30], peak;

	int build(int l, int r) {
		if (l == r) {
			++peak; L[peak] = R[peak] = peak; return peak;
		}
		int u = ++peak;
		L[u] = build(l, mid);
		R[u] = build(mid + 1, r);
		return u;
	}	
	
	int upd(int v, int l, int r, int x, int val) { // a[x] += val
		if (r < x || l > x) return v;
		if (l == r) {
			++peak; T[peak] = T[v] + val; L[peak] = R[peak] = peak; return peak;
		}
		int u = ++peak;
		L[u] = upd(L[v], l, mid, x, val);
		R[u] = upd(R[v], mid + 1, r, x, val);
		T[u] = T[L[u]] + T[R[u]];
		//printf("u = %d l = %d r = %d -> leftchild = %d rightchild = %d => T = %d\n", u, l, r, L[u], R[u], T[u]);
		return u;
	}
} pit;

struct IT {
	int T[N << 2];
	int lz[N << 2];

	IT() {
		memset(T, 0, sizeof T);
		memset(lz, -1, sizeof lz);
	}

	void push(int v, int l, int r) {
		if (lz[v] == -1) return;
		if (l < r) lz[v << 1] = lz[v], lz[v << 1 | 1] = lz[v];
		T[v] = lz[v] * (r - l + 1);
		lz[v] = -1;
	}

	void upd(int v, int l, int r, int L, int R, int val) { // [L...R] -> val
		push(v, l, r);
		if (R < l || L > r) return;
		if (L <= l && r <= R) {
			lz[v] = val; push(v, l, r); return;
		}
		upd(v << 1, l, mid, L, R, val);
		upd(v << 1 | 1, mid + 1, r, L, R, val);
		T[v] = T[v << 1] + T[v << 1 | 1];
	}
} it;

// --------------------------------

void init(int _n, int A[], int B[]) {
	n = _n;
	for (int i = 0; i < n; ++i) {
		cntRig[B[i]]++;
		lef[A[i]].push_back(B[i]);
	}
	pit.build(1, n);
	ver[0] = 1;
	for (int i = 1; i <= n; ++i) {
		ver[i] = ver[i - 1];
		if (cntRig[i - 1]) {
			ver[i] = pit.upd(ver[i], 1, n, i - 1, -cntRig[i - 1]); // delete
		}
		for (auto &j : lef[i]) {
			ver[i] = pit.upd(ver[i], 1, n, j, +1); // add
		}
	}
}

pair<int, int> find(int u, int v, int w, int l, int r, int leftmost, int gap) { 
	// u, v: two different versions in PIT (u: ver[s[i]], v: ver[s[i - 1]])
	// w: current node in IT
	it.push(w, l, r);
	if (r < leftmost) return {0, 0};
	if (l >= leftmost) {
		if (l == r) {
			if (pit.T[u] - pit.T[v] + it.T[w] >= gap) return {l, pit.T[u] - pit.T[v] + it.T[w] - gap /*rem*/}; 
			else return {0, pit.T[u] - pit.T[v] + it.T[w]}; // cannot find 
		}
		if (pit.T[u] - pit.T[v] + it.T[w] < gap) return {0, pit.T[u] - pit.T[v] + it.T[w]};
	}

	auto ret = find(pit.L[u], pit.L[v], w << 1, l, mid, leftmost, gap);
	if (!ret.first) return find(pit.R[u], pit.R[v], w << 1 | 1, mid + 1, r, leftmost, gap - ret.second);
	else return ret;
}

pair<int,int> t[200005];
int can(int m, int sz[]) {
	sort(sz, sz + m);
	int k = 0;
	for (int i = 0; i < m; ++i) {
		if (i > 0 && sz[i] == sz[i - 1]) {
			t[k].second += sz[i];
		} else {
			t[++k] = {sz[i], sz[i]};
		}
	}
	m = k;

	for (int i = 1; i <= m; ++i) {
		auto cur = find(ver[t[i].first], ver[t[i - 1].first], 1, 1, n, t[i].first, t[i].second);
		if (cur.first == 0) { // cannot find
			it.upd(1, 1, n, 1, n, 0);
			return false;
		}

		it.upd(1, 1, n, 1, cur.first, 0); // all 0s
		it.upd(1, 1, n, cur.first, cur.first, cur.second); // cur.second = rem
	}

	it.upd(1, 1, n, 1, n, 0);
	return true;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...