Submission #1704

# Submission time Handle Problem Language Result Execution time Memory
1704 2013-07-12T16:11:53 Z model_code Jousting tournament (IOI12_tournament) C++
100 / 100
150 ms 191876 KB
/*
	O(N*logN) solution for Tournament.
	
	Author: Giovanni Paolini
*/

#include <cstdio>
#include <iostream>
#include <cassert>
#include <vector>
#include <queue>

using namespace std;

int const MAXN = 2000000;
int const MAXLOGN = 22;

struct Node {
	int start;
	int end;
	
	bool all_white; // True if the interval contains good knights only
	bool almost_all_white; // True if the interval contains good knights only, except at most the first knight
	
	int best_result; // The maximum length of a victory-path finishing in that node
	int where_best; // Where is the best_result achieved
	
	Node() {}
	
	Node(int _start, int _end) {
		start = _start;
		end = _end;
		best_result = 0;
	}
};

int n,c,o;

bool rank[MAXN];

// Range tree
int range_tree[MAXLOGN][MAXN];
int size; // the size of the range tree

void make_range_tree() {
	
	int m = n;
	int step = 0;
	
	while ( m > 0 ) {
		for (int i=0; i<m; ++i) {
			if ( step == 0 ) range_tree[step][i] = 1;
			else {
				range_tree[step][i] = range_tree[step-1][2*i] + range_tree[step-1][2*i+1];
			}
		}
		
		if ( m > 1 ) m = (m+1)/2;
		else m = 0;
		step++;
	}
	
	size = step;
	
}

void change (int k, int delta) { // Change the value of position k by delta
	int m = k;
	for (int step = 0; step < size; ++step) {
		
		range_tree[step][m] += delta;
		m /= 2;
		
	}
}

int find_knight (int k, int step, int m) { // Find the (initial) position of the k-th living knight, starting from a given node (step,m) of the range tree
	if ( k > range_tree[step][m] ) return n;
	
	if ( step == 0 ) {
		assert(k == 1);
		return m;
	}
	
	if ( range_tree[step-1][2*m] >= k ) return find_knight( k, step-1, 2*m );
	else return find_knight( k - range_tree[step-1][2*m], step-1, 2*m+1 );
}


// Calls tree

vector<Node> calls_tree;
int father[MAXN]; // The index of current interval of the knight

int GetBestPosition(int N, int C, int R, int *K, int *S, int *E) {
	
	n = N;
	c = C;
	int o = R;
	
	make_range_tree();
	
	rank[0] = 1;
	Node nodo = Node( 0, 0 );
	nodo.all_white = 1;
	nodo.almost_all_white = 1;
	nodo.where_best = 0;
	calls_tree.push_back( nodo );
	father[0] = 0;
	
	for (int i=1; i<n; ++i) {
		int r = K[i-1];
		rank[i] = (r > o);
		father[i] = i;
		
		Node nodo = Node( i, i );
		nodo.all_white = !rank[i];
		nodo.almost_all_white = 1;
		nodo.where_best = i;
		calls_tree.push_back( nodo );
	}
	
	for (int i=0; i<c; ++i) {
		
		int s = S[i]+1;
		int e = E[i]+1;
		
		int first = find_knight( s, size-1, 0 );
		int last = find_knight( e+1, size-1, 0 ) - 1;
		
		Node interval = Node( first, last ); // The new interval
		
		bool all_white = 1;
		bool almost_all_white = 1;
		
		int best_child = -1;
		int the_best = -1;
		
		queue<int> to_change;
		
		for (int j=s; j<=e; ++j) {
		
			int knight = find_knight( j, size-1, 0 );
			if ( j > s ) to_change.push( knight );
			int old_int = father[knight];
			
			father[knight] = calls_tree.size();
			
			if ( calls_tree[old_int].all_white == 0 ) {
				all_white = 0;
				
				if ( j > s ) almost_all_white = 0;
				else if ( calls_tree[old_int].almost_all_white == 0 ) almost_all_white = 0;
			}
			
			if ( calls_tree[old_int].best_result > the_best ) {
				the_best = calls_tree[old_int].best_result;
				best_child = old_int;
			}
		}
		
		while ( !(to_change.empty()) ) {
			int knight = to_change.front();
			to_change.pop();
			change( knight, -1 );
		}
		
		interval.all_white = all_white;
		interval.almost_all_white = almost_all_white;
		
		if ( almost_all_white ) {
			interval.best_result = the_best + 1;
			interval.where_best = calls_tree[ best_child ].where_best;
			// Found an interval for which it is possible to win interval.best_result times by starting in position interval.where_best
		}
		else {
			interval.best_result = the_best;
			interval.where_best = calls_tree[ best_child ].where_best;
		}
		
		calls_tree.push_back(interval);
	}
	
	int t = calls_tree.size();
	
	return calls_tree[t-1].where_best;
}
# Verdict Execution time Memory Grader output
1 Correct 0 ms 183048 KB Output is correct
2 Correct 0 ms 183048 KB Output is correct
3 Correct 0 ms 183048 KB Output is correct
4 Correct 0 ms 183048 KB Output is correct
5 Correct 0 ms 183048 KB Output is correct
6 Correct 0 ms 183048 KB Output is correct
7 Correct 0 ms 183048 KB Output is correct
8 Correct 0 ms 183048 KB Output is correct
9 Correct 0 ms 183048 KB Output is correct
10 Correct 0 ms 183048 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 183048 KB Output is correct
2 Correct 5 ms 183588 KB Output is correct
3 Correct 1 ms 183388 KB Output is correct
4 Correct 5 ms 183588 KB Output is correct
5 Correct 6 ms 183584 KB Output is correct
6 Correct 4 ms 183412 KB Output is correct
7 Correct 4 ms 183588 KB Output is correct
8 Correct 3 ms 183588 KB Output is correct
9 Correct 2 ms 183388 KB Output is correct
10 Correct 6 ms 183592 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 61 ms 187336 KB Output is correct
2 Correct 144 ms 191876 KB Output is correct
3 Correct 44 ms 187332 KB Output is correct
4 Correct 142 ms 191876 KB Output is correct
5 Correct 141 ms 191840 KB Output is correct
6 Correct 138 ms 191612 KB Output is correct
7 Correct 147 ms 191876 KB Output is correct
8 Correct 150 ms 191876 KB Output is correct
9 Correct 37 ms 187284 KB Output is correct
10 Correct 45 ms 187320 KB Output is correct