답안 #170529

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
170529 2019-12-25T14:55:53 Z oolimry 늑대인간 (IOI18_werewolf) C++14
100 / 100
807 ms 69904 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);
	
	
	///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];
	}
	
	///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);
	
	
	///So basically we build a range max segment tree on the wolf indeces
	///For all human indeces lower than qu.humanHigh, we update the human index on the wolf segment tree
	///If the range max of the wolf segment tree is larger than q.humanLow, then we can conclude that the two ranges intersect
	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);
			ptr++;
		}
		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 19320 KB Output is correct
2 Correct 19 ms 19192 KB Output is correct
3 Correct 18 ms 19192 KB Output is correct
4 Correct 49 ms 19196 KB Output is correct
5 Correct 23 ms 19192 KB Output is correct
6 Correct 19 ms 19192 KB Output is correct
7 Correct 19 ms 19192 KB Output is correct
8 Correct 19 ms 19192 KB Output is correct
9 Correct 25 ms 19216 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 19320 KB Output is correct
2 Correct 19 ms 19192 KB Output is correct
3 Correct 18 ms 19192 KB Output is correct
4 Correct 49 ms 19196 KB Output is correct
5 Correct 23 ms 19192 KB Output is correct
6 Correct 19 ms 19192 KB Output is correct
7 Correct 19 ms 19192 KB Output is correct
8 Correct 19 ms 19192 KB Output is correct
9 Correct 25 ms 19216 KB Output is correct
10 Correct 26 ms 19960 KB Output is correct
11 Correct 26 ms 19988 KB Output is correct
12 Correct 26 ms 19960 KB Output is correct
13 Correct 26 ms 20028 KB Output is correct
14 Correct 26 ms 19960 KB Output is correct
15 Correct 28 ms 20088 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 664 ms 63956 KB Output is correct
2 Correct 600 ms 65512 KB Output is correct
3 Correct 611 ms 63992 KB Output is correct
4 Correct 637 ms 64060 KB Output is correct
5 Correct 688 ms 64192 KB Output is correct
6 Correct 710 ms 64248 KB Output is correct
7 Correct 629 ms 63992 KB Output is correct
8 Correct 574 ms 65600 KB Output is correct
9 Correct 544 ms 64248 KB Output is correct
10 Correct 571 ms 63996 KB Output is correct
11 Correct 583 ms 63992 KB Output is correct
12 Correct 650 ms 64120 KB Output is correct
13 Correct 624 ms 65784 KB Output is correct
14 Correct 633 ms 65636 KB Output is correct
15 Correct 606 ms 65708 KB Output is correct
16 Correct 628 ms 65680 KB Output is correct
17 Correct 634 ms 63964 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 ms 19320 KB Output is correct
2 Correct 19 ms 19192 KB Output is correct
3 Correct 18 ms 19192 KB Output is correct
4 Correct 49 ms 19196 KB Output is correct
5 Correct 23 ms 19192 KB Output is correct
6 Correct 19 ms 19192 KB Output is correct
7 Correct 19 ms 19192 KB Output is correct
8 Correct 19 ms 19192 KB Output is correct
9 Correct 25 ms 19216 KB Output is correct
10 Correct 26 ms 19960 KB Output is correct
11 Correct 26 ms 19988 KB Output is correct
12 Correct 26 ms 19960 KB Output is correct
13 Correct 26 ms 20028 KB Output is correct
14 Correct 26 ms 19960 KB Output is correct
15 Correct 28 ms 20088 KB Output is correct
16 Correct 664 ms 63956 KB Output is correct
17 Correct 600 ms 65512 KB Output is correct
18 Correct 611 ms 63992 KB Output is correct
19 Correct 637 ms 64060 KB Output is correct
20 Correct 688 ms 64192 KB Output is correct
21 Correct 710 ms 64248 KB Output is correct
22 Correct 629 ms 63992 KB Output is correct
23 Correct 574 ms 65600 KB Output is correct
24 Correct 544 ms 64248 KB Output is correct
25 Correct 571 ms 63996 KB Output is correct
26 Correct 583 ms 63992 KB Output is correct
27 Correct 650 ms 64120 KB Output is correct
28 Correct 624 ms 65784 KB Output is correct
29 Correct 633 ms 65636 KB Output is correct
30 Correct 606 ms 65708 KB Output is correct
31 Correct 628 ms 65680 KB Output is correct
32 Correct 634 ms 63964 KB Output is correct
33 Correct 680 ms 64100 KB Output is correct
34 Correct 502 ms 46328 KB Output is correct
35 Correct 695 ms 65640 KB Output is correct
36 Correct 686 ms 64248 KB Output is correct
37 Correct 733 ms 65080 KB Output is correct
38 Correct 713 ms 64504 KB Output is correct
39 Correct 663 ms 68728 KB Output is correct
40 Correct 807 ms 69496 KB Output is correct
41 Correct 661 ms 64632 KB Output is correct
42 Correct 614 ms 64324 KB Output is correct
43 Correct 745 ms 68708 KB Output is correct
44 Correct 683 ms 65096 KB Output is correct
45 Correct 623 ms 69252 KB Output is correct
46 Correct 609 ms 68856 KB Output is correct
47 Correct 613 ms 65884 KB Output is correct
48 Correct 610 ms 65784 KB Output is correct
49 Correct 615 ms 66040 KB Output is correct
50 Correct 624 ms 65528 KB Output is correct
51 Correct 778 ms 69760 KB Output is correct
52 Correct 786 ms 69904 KB Output is correct