답안 #170524

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
170524 2019-12-25T14:45:59 Z oolimry 늑대인간 (IOI18_werewolf) C++14
100 / 100
786 ms 81252 KB
#include "werewolf.h"

#include <bits/stdc++.h>
using namespace std;

const int maxN = 400000;
typedef pair<int,int> ii;
struct UFDS{
	int p[maxN];
	void reset(int n){
		for(int i = 0;i < n;i++) p[i] = i;
	}
	int findSet(int u){
		if(p[u] == u) return u;
		else{
			p[u] = findSet(p[u]);
			return p[u]; ///use path compression only
		}
	}
	void unionSet(int u, int v){
		u = findSet(u);
		v = findSet(v);
		if(u == v) return;
		if(u > v) swap(u,v);
		p[u] = v; ///don't union by rank, instead return the largest value to make tree building easier
	}
};

struct query{
	int start;
	int end;
	int L;
	int R;
	int id;
	int humanSubtree; ///idx of subtree
	int humanLow; ///preorder left endpoint
	int humanHigh; ///preorder right endpoint
	int wolfSubtree; ///idx of subtree
	int wolfLow; ///preorder left endpoint
	int wolfHigh; ///preorder right endpoint
};

struct edge{
	int u;
	int v;
	int w;
};

struct tree{
	vector<int> child[maxN];
	int low[maxN];
	int high[maxN];
	int cnt = 0;
	void addEdge(int parent, int c){
		child[parent].push_back(c);
	}
	
	///basically like a preorder, but don't label the non-leaves
	void dfs(int u){
		low[u] = 102345678;
		high[u] = -1;
		if(child[u].empty()){
			low[u] = cnt;
			high[u] = cnt;
			cnt++;
			return;
		}
		for(int v : child[u]){
			dfs(v);
			low[u] = min(low[u],low[v]);
			high[u] = max(high[u],high[v]);
		}
	}
};

struct segment{
	int seg[maxN]; int n;
	void create(int nn){
		n = nn;
		for(int i = 0;i < 2*n;i++) seg[i] = -1e8;
	}
	
	void update(int i, int v){
		i += n;
		while(i > 0){
			seg[i] = max(seg[i],v);
			i >>= 1;
		}
	}
	
	int Query(int l, int r){
		int ans = -1e8;
		for(l += n, r += n;l < r;l >>= 1, r >>= 1){
			if(l&1){
				ans = max(ans, seg[l]);
				l++;
			}
			if(r&1){
				r--;
				ans = max(ans, seg[r]);
			}
		}
		return ans;
	}
};

bool edgeComp(edge a, edge b){
	return a.w < b.w;
}

bool queryCompHuman(query a, query b){
	return a.L > b.L;
}

bool queryCompWolf(query a, query b){
	return a.R < b.R;
}

bool queryHighComp(query a, query b){
	return a.humanHigh < b.humanHigh;
}

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 m = X.size();
	int q = S.size();
	
	vector<int> answer;
	answer.assign(q,0);
	
	query queries[q+1];
	for(int i = 0;i < q;i++){
		queries[i] = {S[i],E[i],L[i],R[i],i,-1,-1,-1,-1};
	}
	
	edge edges[m];
	UFDS uf;
	tree human; tree wolf;
	
	///Building the tree for the start/human form
	///In the new tree, if a node has a value X, all leaves in that subtree will be reachable if L = X, (i.e. all leaves nodes have value >= X)
	for(int i = 0;i < m;i++) edges[i] = {X[i],Y[i],min(X[i],Y[i])};
	sort(edges,edges+m,edgeComp);
	reverse(edges,edges+m); ///decreasing weight
	sort(queries,queries+q,queryCompHuman); ///decreasing L
	queries[q].L = -1; ///dummy element to ensure entire tree is comepleted
	uf.reset(2*n);
	int newNode = n;
	int edgePtr = 0;
	
	for(int i = 0;i <= q;i++){
		while(edgePtr < m && edges[edgePtr].w >= queries[i].L){
			int u = uf.findSet(edges[edgePtr].u);
			int v = uf.findSet(edges[edgePtr].v);
			edgePtr++;
			if(u == v) continue;
			
			///connect the two greatest parents to another parent
			uf.unionSet(u,newNode);
			uf.unionSet(v,newNode);
			human.addEdge(newNode,u);
			human.addEdge(newNode,v);
			newNode++;	
		}
		
		///the representitive subtree is the subtree of the greatest parent at the current moment
		if(i != q) queries[i].humanSubtree = uf.findSet(queries[i].start);
	}
	
	
	///Building the tree for the end/wolf form
	///In the new tree, if a node has a value X, all leaves in that subtree will be reachable if R = X, (i.e. all leaves nodes have value <= X)
	for(int i = 0;i < m;i++) edges[i] = {X[i],Y[i],max(X[i],Y[i])};
	sort(edges,edges+m,edgeComp); ///increasing weight
	sort(queries,queries+q,queryCompWolf); ///increasing R
	queries[q].R = 1e7; ///dummy element to ensure entire tree is comepleted
	uf.reset(2*n);
	newNode = n;
	edgePtr = 0;
	
	for(int i = 0;i <= q;i++){
		while(edgePtr < m && edges[edgePtr].w <= queries[i].R){
			int u = uf.findSet(edges[edgePtr].u);
			int v = uf.findSet(edges[edgePtr].v);
			edgePtr++;
			if(u == v) continue;
			
			///connect the two greatest parents to another parent
			uf.unionSet(u,newNode);
			uf.unionSet(v,newNode);
			wolf.addEdge(newNode,u);
			wolf.addEdge(newNode,v);
			newNode++;	
		}
		
		///the representitive subtree is the subtree of the greatest parent at the current moment
		if(i != q) queries[i].wolfSubtree = uf.findSet(queries[i].end);
	}
	
	///Now, we run a preorder on the tree, but don't label to edges. This way, we can convert each query into checking whether two sets of elements have any element in common
	human.dfs(2 * n - 2);
	wolf.dfs(2 * n - 2);
	
	
	//for(int i = 0;i < 2*n-1;i++){
	//	cout << human.low[i] << " " << human.high[i] << " " << wolf.low[i] << " " << wolf.high[i] << "\n";
	//}
	///Low and High represent the ranges, we need to check if the human range and the wolf range intersect
	///Note: intersect here means the following:
	///In each of the human tree, each node on the original graph corresponds to another number on the human tree
	///Same for the wolf tree
	///Each query is a consecutive range of numbers of both trees.
	///If we convert each of the numbers in the ranges of the trees back to the original index, we query whether there exist a vertex that is shared on both graphs
	for(int i = 0;i < q;i++){
		queries[i].humanLow = human.low[queries[i].humanSubtree];
		queries[i].humanHigh = human.high[queries[i].humanSubtree];
		queries[i].wolfLow = wolf.low[queries[i].wolfSubtree];
		queries[i].wolfHigh = wolf.high[queries[i].wolfSubtree];
		
		//cout << queries[i].id << " " << queries[i].humanSubtree << " " << queries[i].wolfSubtree << " " << queries[i].humanLow << " " << queries[i].humanHigh << " " << queries[i].wolfLow << " " << queries[i].wolfHigh << "\n";
	}
	
	///Use a segment tree to answer this type of queries
	segment seg;
	seg.create(n);
	
	///convert stores which number of the human tree corresponds to which number on the wolf tree
	ii convert[n];
	for(int i = 0;i < n;i++) convert[i] = ii(human.low[i],wolf.low[i]);
	sort(convert,convert + n);
	sort(queries,queries+q,queryHighComp);
	
	int ptr = 0;
	for(int i = 0;i < q;i++){
		query qu = queries[i];
		while(ptr < n && qu.humanHigh >= convert[ptr].first){
			seg.update(convert[ptr].second, convert[ptr].first);
			//cout << convert[ptr].second << " " << convert[ptr].first << "\n";
			ptr++;
		}
		//cout << qu.id << " " << seg.Query(qu.wolfLow, qu.wolfHigh + 1) << "\n";
		if(seg.Query(qu.wolfLow, qu.wolfHigh + 1) >= qu.humanLow){
			answer[qu.id] = 1;
		}
		else{
			answer[qu.id] = 0;
		}
	}
	

	return answer;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 19192 KB Output is correct
2 Correct 20 ms 19192 KB Output is correct
3 Correct 23 ms 19192 KB Output is correct
4 Correct 19 ms 19192 KB Output is correct
5 Correct 19 ms 19192 KB Output is correct
6 Correct 19 ms 19320 KB Output is correct
7 Correct 19 ms 19192 KB Output is correct
8 Correct 19 ms 19192 KB Output is correct
9 Correct 19 ms 19192 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 19192 KB Output is correct
2 Correct 20 ms 19192 KB Output is correct
3 Correct 23 ms 19192 KB Output is correct
4 Correct 19 ms 19192 KB Output is correct
5 Correct 19 ms 19192 KB Output is correct
6 Correct 19 ms 19320 KB Output is correct
7 Correct 19 ms 19192 KB Output is correct
8 Correct 19 ms 19192 KB Output is correct
9 Correct 19 ms 19192 KB Output is correct
10 Correct 25 ms 19960 KB Output is correct
11 Correct 25 ms 19960 KB Output is correct
12 Correct 26 ms 19900 KB Output is correct
13 Correct 26 ms 19964 KB Output is correct
14 Correct 26 ms 20000 KB Output is correct
15 Correct 27 ms 20028 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 733 ms 72112 KB Output is correct
2 Correct 602 ms 73808 KB Output is correct
3 Correct 608 ms 72316 KB Output is correct
4 Correct 642 ms 72312 KB Output is correct
5 Correct 653 ms 72184 KB Output is correct
6 Correct 663 ms 72304 KB Output is correct
7 Correct 636 ms 72200 KB Output is correct
8 Correct 589 ms 73848 KB Output is correct
9 Correct 543 ms 72184 KB Output is correct
10 Correct 572 ms 72184 KB Output is correct
11 Correct 589 ms 72288 KB Output is correct
12 Correct 621 ms 72284 KB Output is correct
13 Correct 610 ms 73720 KB Output is correct
14 Correct 629 ms 73848 KB Output is correct
15 Correct 618 ms 73800 KB Output is correct
16 Correct 613 ms 73900 KB Output is correct
17 Correct 647 ms 72140 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 19192 KB Output is correct
2 Correct 20 ms 19192 KB Output is correct
3 Correct 23 ms 19192 KB Output is correct
4 Correct 19 ms 19192 KB Output is correct
5 Correct 19 ms 19192 KB Output is correct
6 Correct 19 ms 19320 KB Output is correct
7 Correct 19 ms 19192 KB Output is correct
8 Correct 19 ms 19192 KB Output is correct
9 Correct 19 ms 19192 KB Output is correct
10 Correct 25 ms 19960 KB Output is correct
11 Correct 25 ms 19960 KB Output is correct
12 Correct 26 ms 19900 KB Output is correct
13 Correct 26 ms 19964 KB Output is correct
14 Correct 26 ms 20000 KB Output is correct
15 Correct 27 ms 20028 KB Output is correct
16 Correct 733 ms 72112 KB Output is correct
17 Correct 602 ms 73808 KB Output is correct
18 Correct 608 ms 72316 KB Output is correct
19 Correct 642 ms 72312 KB Output is correct
20 Correct 653 ms 72184 KB Output is correct
21 Correct 663 ms 72304 KB Output is correct
22 Correct 636 ms 72200 KB Output is correct
23 Correct 589 ms 73848 KB Output is correct
24 Correct 543 ms 72184 KB Output is correct
25 Correct 572 ms 72184 KB Output is correct
26 Correct 589 ms 72288 KB Output is correct
27 Correct 621 ms 72284 KB Output is correct
28 Correct 610 ms 73720 KB Output is correct
29 Correct 629 ms 73848 KB Output is correct
30 Correct 618 ms 73800 KB Output is correct
31 Correct 613 ms 73900 KB Output is correct
32 Correct 647 ms 72140 KB Output is correct
33 Correct 687 ms 72228 KB Output is correct
34 Correct 511 ms 57720 KB Output is correct
35 Correct 698 ms 74232 KB Output is correct
36 Correct 685 ms 72440 KB Output is correct
37 Correct 695 ms 73208 KB Output is correct
38 Correct 697 ms 72704 KB Output is correct
39 Correct 665 ms 76884 KB Output is correct
40 Correct 779 ms 80936 KB Output is correct
41 Correct 712 ms 72824 KB Output is correct
42 Correct 641 ms 72568 KB Output is correct
43 Correct 741 ms 78300 KB Output is correct
44 Correct 711 ms 73268 KB Output is correct
45 Correct 626 ms 77356 KB Output is correct
46 Correct 633 ms 77120 KB Output is correct
47 Correct 612 ms 74004 KB Output is correct
48 Correct 605 ms 73848 KB Output is correct
49 Correct 611 ms 73988 KB Output is correct
50 Correct 627 ms 73848 KB Output is correct
51 Correct 786 ms 81244 KB Output is correct
52 Correct 775 ms 81252 KB Output is correct