Submission #147511

# Submission time Handle Problem Language Result Execution time Memory
147511 2019-08-29T21:48:30 Z faremy Highway Tolls (IOI18_highway) C++14
0 / 100
36 ms 10744 KB
#include "highway.h"

#include <queue>
#include <algorithm>
#include <iostream>


struct Edge
{
	Edge(int d, int i) : dest(d), id(i) {}
	int dest, id;

	bool operator ==(const Edge &other) const
	{
		return (dest == other.dest && id == other.id);
	}
};

const int MAXN = 90000;

std::vector<Edge> graph[MAXN];
std::vector<int> trafficCondition;

std::queue<int> bfs;
std::vector<Edge> tree[MAXN];
int parent[MAXN], parentEdge[MAXN];

std::vector<int> opti;


inline void toogle(int road)
{
	trafficCondition[road] = 1 - trafficCondition[road];
}

int findroot(int left, int right, long long expectedLength)
{
	if (left == right)
		return MAXN;
	int middle = (left + right) / 2;

	for (int iNode = 0; iNode < middle; iNode++)
		for (Edge &edge : graph[iNode])
			toogle(edge.id);

	long long shortestPath = ask(trafficCondition);
	for (int iNode = 0; iNode < middle; iNode++)
		for (Edge &edge : graph[iNode])
			toogle(edge.id);
	
	if (shortestPath > expectedLength)
		return std::min(middle, findroot(left, middle, expectedLength));
	return findroot(middle + 1, right, expectedLength);
}

void buildtree(int root)
{
	bfs.emplace(root);
	parent[root] = -1;
	
	std::fill_n(parentEdge, MAXN, -1);
	parentEdge[root] = -2;

	while (!bfs.empty())
	{
		int node = bfs.front();
		bfs.pop();

		for (Edge &edge : graph[node])
		{
			toogle(edge.id);
			if (parentEdge[edge.dest] == -1)
			{
				tree[node].emplace_back(edge);
				parent[edge.dest] = node;
				parentEdge[edge.dest] = edge.id;
				
				toogle(edge.id);
				bfs.emplace(edge.dest);
			}
		}
	}
}

void toogledepth(int node, int depth, int maxDepth)
{
	if (depth == maxDepth)
		return;
	
	for (Edge &edge : tree[node])
	{
		toogle(edge.id);
		toogledepth(edge.dest, depth + 1, maxDepth);
	}
}

void makedepthset(int node, std::vector<int> &nodeSet, int depth, int maxDepth)
{
	if (depth == maxDepth)
	{
		nodeSet.emplace_back(node);
		return;
	}

	for (Edge &edge : tree[node])
		makedepthset(edge.dest, nodeSet, depth + 1, maxDepth);
}

int searchextremity(std::vector<int> candidates, long long expectedLength, long long whenUpd)
{
	if (candidates.size() == 1)
		return candidates[0];

	for (int iNode = 0; iNode < (int)candidates.size() / 2; iNode++)
		toogle(parentEdge[iNode]);

	long long shortestPath = ask(trafficCondition);
	for (int iNode = 0; iNode < (int)candidates.size() / 2; iNode++)
		toogle(parentEdge[iNode]);

	if (shortestPath == expectedLength + whenUpd)
	{
		opti = std::vector<int>(candidates.begin() + candidates.size() / 2, candidates.end());
		return searchextremity(std::vector<int>(candidates.begin(), candidates.begin() + candidates.size() / 2), expectedLength, -1);
	}

	if (shortestPath > expectedLength)
		return searchextremity(std::vector<int>(candidates.begin(), candidates.begin() + candidates.size() / 2), expectedLength, whenUpd);
	return searchextremity(std::vector<int>(candidates.begin() + candidates.size() / 2, candidates.end()), expectedLength, whenUpd);
}

void find_pair(int N, std::vector<int> U, std::vector<int> V, int A, int B)
{
	for (int iEdge = 0; iEdge < (int)U.size(); iEdge++)
	{
		graph[U[iEdge]].emplace_back(V[iEdge], iEdge);
		graph[V[iEdge]].emplace_back(U[iEdge], iEdge);
	}

	trafficCondition.resize(U.size(), 0);
	long long shortestPath = ask(trafficCondition);
	long long edgesOnPath = shortestPath / (long long)A;

	int root = findroot(0, N, shortestPath);
	buildtree(root);

	toogledepth(root, 0, edgesOnPath / 2);
	long long newShort = ask(trafficCondition);
	toogledepth(root, 0, edgesOnPath / 2);

	if (newShort == edgesOnPath * (long long)B)
	{
		std::vector<int> nodes;
		makedepthset(root, nodes, 0, edgesOnPath / 2);
		int s = searchextremity(nodes, shortestPath, B - A);
		int t = searchextremity(opti, shortestPath, -1);
		answer(s, t);
	}
	else
	{
		long long Sdepth = (newShort - shortestPath - (edgesOnPath / 2LL) * (long long)B) / (long long)B;
		std::vector<int> nodes;
		makedepthset(root, nodes, 0, edgesOnPath - Sdepth);
		int t = searchextremity(nodes, shortestPath, -1);

		int block = t;
		while (parent[block] != -1)
		{
			tree[parent[block]].erase(std::find(tree[parent[block]].begin(), tree[parent[block]].end(), Edge(block, parentEdge[block])));
			block = parent[block];
		}

		nodes.clear();
		makedepthset(root, nodes, 0, Sdepth);
		int s = searchextremity(nodes, shortestPath, -1);
		answer(s, t);
	}
}
# Verdict Execution time Memory Grader output
1 Incorrect 8 ms 4900 KB Output is incorrect: more than 100 calls to ask
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 8 ms 4860 KB Output is incorrect: {s, t} is wrong
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 32 ms 10744 KB Execution killed with signal 11 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 10 ms 4984 KB Output is incorrect: more than 100 calls to ask
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 36 ms 5752 KB Output is incorrect: more than 100 calls to ask
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 24 ms 5752 KB Output is incorrect: {s, t} is wrong
2 Halted 0 ms 0 KB -