답안 #431877

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
431877 2021-06-17T16:35:16 Z albertolg101 늑대인간 (IOI18_werewolf) C++17
0 / 100
1265 ms 100880 KB
#include <bits/stdc++.h>
#include "werewolf.h"
	
using namespace std;
using pii = pair<int, int>;

struct dsu 
{
	vector<int> parent;
	vector<bool> flag;

	dsu(int n)
	{
		flag.resize(n);

		for(int i = 0 ; i < n ; i++)
			parent.push_back(i);
	}

	int Find (int nod)
	{
		if(parent[nod] == nod)
			return nod;

		return parent[nod] = Find(parent[nod]);
	}

	bool Union (int nod_a, int nod_b, bool sol)
	{
		int x = Find(nod_a),
			y = Find(nod_b);

		if(!flag[x] or !flag[y])
			return false;

		if(!sol)
			parent[min(x, y)] = max(x, y);

		if(sol)
			parent[max(x, y)] = min(x, y);

		return x != y;
	}

	void activate (int x)
	{
		flag[x] = true;
	}
};

vector<int> t;

void update (int x, int xend, int nod, int pos, int val)
{
	if(x == xend)
		return void(t[nod] = val);

	int mid = (x + xend) / 2;
	(pos <= mid ? update(x, mid, nod*2, pos, val) : update(mid+1, xend, nod*2+1, pos, val));
	
	t[nod] = max(t[nod*2], t[nod*2+1]);
}

int query (int x, int xend, int nod, int l, int r)
{
	if(x > r or xend < l)
		return 0;
	
	if(l <= x and xend <= r)
		return t[nod];

	int mid = (x + xend) / 2;
	return max(query(x, mid, nod*2, l, r), query(mid+1, xend, nod*2+1, l, r));
}
	
std::vector<int> check_validity(int n, std::vector<int> X, std::vector<int> Y,
								std::vector<int> S, std::vector<int> E,
								std::vector<int> L, std::vector<int> R) {
	
	int Q = L.size(), m = X.size();
	vector<vector<int>> g(n);
	
	for(int i = 0 ; i < m ; i++)
	{
		g[X[i]].push_back(Y[i]);
		g[Y[i]].push_back(X[i]);
	}

	dsu dsuL(n), dsuR(n);
	vector<vector<int>> gl(n), gr(n);

	for(int i = 0 ; i < n ; i++)
	{
		int nod = i;
		dsuL.activate(i);
		sort(g[i].rbegin(), g[i].rend());

		for(auto j: g[i])
		{
			int x = dsuL.Find(j);

			if(dsuL.Union(nod, x, false))
			{
				gl[nod].push_back(x);
				gl[x].push_back(nod);
				nod = dsuL.Find(nod);
			}
		}
	}

	for(int i = n - 1 ; i >= 0 ; i--)
	{
		int nod = i;
		dsuR.activate(i);
		reverse(g[i].begin(), g[i].end());

		for(auto j: g[i])
		{
			int x = dsuR.Find(j);

			if(dsuR.Union(nod, x, true))
			{
				gr[nod].push_back(x);
				gr[x].push_back(nod);
				nod = dsuR.Find(nod);
			}
		}
	}

	int cnt = 0;
	vector<int> et, levelL(n), levelR(n);
	vector<pii> indxL(n), indxR(n);
	vector<vector<int>> parentL(n, vector<int> (18)), parentR = parentL;

	function<void(int, int)> dfs1 = [&](int nod, int father)
	{
		indxR[nod].first = et.size();
		et.push_back(nod);

		for(auto i: gl[nod])
		{
			if(i != father)
			{
				levelR[i] = levelR[nod]+1;
				parentR[i][0] = nod;
				dfs1(i, nod);
			}
		}

		indxR[nod].second = et.size() - 1;
	};

	function<void(int, int)> dfs2 = [&](int nod, int father)
	{
		indxL[nod].first = cnt++;
		// cout << nod << ' ' ; 

		for(auto i: gr[nod])
		{
			if(i != father)
			{
				levelL[i] = levelL[nod] + 1;
				parentL[i][0] = nod;
				dfs2(i, nod);
			}
		}

		indxL[nod].second = cnt - 1;
	};

	// cout << endl ;
	dfs1(n-1, -1);
	dfs2(0, -1);
	// cout << endl << endl ;

	for(int nod = 0 ; nod < n ; nod++)
	{
		for(int i = 1 ; i < 18 ; i++)
		{
			if((1<<i) <= levelR[nod])
				parentR[nod][i] = parentR[parentR[nod][i-1]][i-1];

			if((1<<i) <= levelL[nod])
				parentL[nod][i] = parentL[parentL[nod][i-1]][i-1];
		}
	}

	vector<pair<pair<int, bool>, int>> v;

	for(int i = 0 ; i < Q ; i++)
	{
		int nod = E[i];

		for(int j = 17 ; j >= 0 ; j--)
		{
			if((1<<j) <= levelR[nod] and parentR[nod][j] <= R[i])
				nod = parentR[nod][j];
		}

		// cout << E[i] << ' ' << R[i] << ' ' << nod << ' ' << indxR[nod].first << ' ' << indxR[nod].second << endl ;

		v.push_back({{indxR[nod].first, false}, i});
		v.push_back({{indxR[nod].second, true}, i});
	}
	// cout << endl ;

	t.resize(4*n);
	sort(v.rbegin(), v.rend());

	cnt = 0;
	vector<int> ans, mm(Q);

	// cout << endl ;
	// for(int i = v.size() - 1 ; i >= 0 ; i--)
	// 	cout << v[i].first.first << ' ' << v[i].first.second << ' ' << v[i].second << endl ;
	// cout << endl ;

	for(int i = 0 ; i < n ; i++)
	{
		while(v.size() and v.back().first.first == i and !v.back().first.second)
		{
			mm[v.back().second] = ++cnt;
			v.pop_back();
		}

		// cout << "u " << et[i] << ' ' << indxL[et[i]].first << ' ' << cnt << endl ;
		update(1, n, 1, indxL[et[i]].first, cnt);

		while(v.size() and v.back().first.first == i and v.back().first.second)
		{
			int nod = S[v.back().second];

			for(int j = 18 ; j >= 0 ; j--)
			{
				if((1<<j) <= levelL[nod] and parentL[nod][j] >= L[v.back().second])
					nod = parentL[nod][j];
			}

			// cout << nod << ' ' << L[v.back().second] << ' ' << indxL[nod].first << ' ' << indxL[nod].second << ' ' << query(1, n, 1, indxL[nod].first, indxL[nod].second) << ' ' << mm[v.back().second] << endl ;

			ans.push_back(query(1, n, 1, indxL[nod].first, indxL[nod].second) >= mm[v.back().second]);
			v.pop_back();
		}
	}

	return ans;
}
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1265 ms 100880 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 1 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -