結果

問題 No.529 帰省ラッシュ
ユーザー tansunogontansunogon
提出日時 2017-08-01 20:06:54
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 267 ms / 4,500 ms
コード長 13,602 bytes
コンパイル時間 1,704 ms
コンパイル使用メモリ 87,944 KB
実行使用メモリ 28,428 KB
最終ジャッジ日時 2024-05-09 16:48:26
合計ジャッジ時間 6,452 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 2 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 2 ms
5,376 KB
testcase_04 AC 4 ms
5,376 KB
testcase_05 AC 4 ms
5,376 KB
testcase_06 AC 4 ms
5,376 KB
testcase_07 AC 4 ms
5,376 KB
testcase_08 AC 168 ms
15,116 KB
testcase_09 AC 166 ms
15,632 KB
testcase_10 AC 214 ms
19,660 KB
testcase_11 AC 220 ms
19,764 KB
testcase_12 AC 139 ms
13,904 KB
testcase_13 AC 192 ms
28,428 KB
testcase_14 AC 160 ms
19,200 KB
testcase_15 AC 267 ms
19,564 KB
testcase_16 AC 262 ms
19,448 KB
testcase_17 AC 227 ms
25,656 KB
testcase_18 AC 226 ms
26,192 KB
testcase_19 AC 230 ms
22,860 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
In member function 'void SegTree::update(int, int)',
    inlined from 'int Solver::query2(int, int)' at main.cpp:674:36:
main.cpp:50:71: warning: 'group_index_max' may be used uninitialized [-Wmaybe-uninitialized]
   50 |                         int value2 = data_[child_begin + (child_index ^ 1)];
      |                                                          ~~~~~~~~~~~~~^~~~
main.cpp: In member function 'int Solver::query2(int, int)':
main.cpp:611:21: note: 'group_index_max' was declared here
  611 |                 int group_index_max = -1;
      |                     ^~~~~~~~~~~~~~~

ソースコード

diff #

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <functional>

class SegTree
{
public:
	// in the case where n = 3,
	//
	// [--3--]
	// [0] [1] [2]
	std::vector<int> data_;
	std::vector<int> index_;
	const int n_;

	SegTree(size_t n) : n_(n)
	{
		int data_size = 0;
		while (n > 0)
		{
			data_size += n;
			n /= 2;
		}
		data_ = std::vector<int>(data_size, -1);
		index_ = std::vector<int>(data_size);
		for (int i = 0; i < n_; ++i)
		{
			index_[i] = i;
		}
	}

	void update(int i, int value)
	{
		assert(i >= 0 && i < n_);

		data_[i] = value;
		int index = i;

		int child_begin = 0;
		int child_index = i;
		int parent_begin = n_;
		int parent_size = n_ / 2;
		int parent_index = i / 2;
		while (parent_index < parent_size)
		{
			int value2 = data_[child_begin + (child_index ^ 1)];
			if (value > value2)
			{
				data_[parent_begin + parent_index] = value;
				index_[parent_begin + parent_index] = index;
			}
			else
			{
				data_[parent_begin + parent_index]
					= value
					= value2;
				index_[parent_begin + parent_index]
					= index
					= index_[child_begin + (child_index ^ 1)];
			}

			child_begin = parent_begin;
			child_index = parent_index;
			parent_begin += parent_size;
			parent_size /= 2;
			parent_index /= 2;
		}
	}

	// max [0, i]
	int getmax(int i, int* index) const
	{
		assert(i < n_);

		int ret_max = -1;
		int index_begin = 0;
		int size = n_;
		while (1)
		{
			if ((i & 1) == 0)
			{
				if (ret_max < data_[index_begin + i])
				{
					ret_max = data_[index_begin + i];
					*index = index_[index_begin + i];
				}
				if (i == 0)
				{
					return ret_max;
				}
				--i;
			}
			index_begin += size;
			size /= 2;
			i /= 2;
		}
	}

	// max [i, j]
	int getmax(int i, int j, int* index) const
	{
		assert(0 <= i && i <= j && j < n_);

		int ret_max = -1;
		int index_begin = 0;
		int size = n_;
		while (1)
		{
			if (i & 1)
			{
				if (ret_max < data_[index_begin + i])
				{
					ret_max = data_[index_begin + i];
					*index = index_[index_begin + i];
				}
				++i;
			}
			if ((j & 1) == 0)
			{
				if (ret_max < data_[index_begin + j])
				{
					ret_max = data_[index_begin + j];
					*index = index_[index_begin + j];
				}
				--j;
			}
			if (i > j)
			{
				return ret_max;
			}
			index_begin += size;
			size /= 2;
			i /= 2;
			j /= 2;
		}
	}
};

class Graph
{
private:
	std::vector<int> edge_data_;
	std::vector<int*> edge_;
	std::vector<int> length_;

public:
	// V : num of vertices
	// E : num of edges
	// vertex[i] = (A[i], B[i])
	Graph(int V, int E, const int A[], const int B[])
	{
		edge_data_ = std::vector<int>(E * 2);
		edge_ = std::vector<int*>(V);
		length_ = std::vector<int>(V);

		for (int i = 0; i < E; ++i)
		{
			++length_[A[i]];
			++length_[B[i]];
		}

		edge_[0] = edge_data_.data();
		for (int i = 0; i < V - 1; ++i)
		{
			edge_[i + 1] = edge_[i] + length_[i];
		}

		memset(length_.data(), 0, V * sizeof(int));

		for (int i = 0; i < E; ++i)
		{
			edge_[A[i]][length_[A[i]]++] = B[i];
			edge_[B[i]][length_[B[i]]++] = A[i];
		}
	}

	// returns num of Vertices
	inline int getV() const
	{
		return length_.size();
	}

	// returns num of edges
	inline int getE() const
	{
		return edge_data_.size() / 2;
	}

	inline int getLength(int index) const
	{
		return length_[index];
	}

	inline int getEdge(int nodeIndex, int index) const
	{
		return edge_[nodeIndex][index];
	}

	void print() const
	{
		for (int i = 0; i < getV(); ++i)
		{
			printf("%d : ", i);
			for (int j = 0; j < getLength(i); ++j)
			{
				printf("%d ", getEdge(i, j));
			}
			printf("\n");
		}
	}
};

class BiconnectGraph_
{
public:
	Graph* g_;
	std::vector<int>* index_;

	BiconnectGraph_(Graph* g)
	{
		Builder builder;
		*this = builder.DecomposeToBiconnectedComponents(g);
	}

protected:
	void close()
	{
		delete g_;
		delete index_;
	}

private:
	BiconnectGraph_(Graph* g, std::vector<int>* index)
		:g_(g), index_(index)
	{}

	class Builder
	{
	public:
		Graph* g;
		std::vector<int> ord;
		std::vector<int> low;
		std::vector<bool> visited;
		int k;

		std::vector<int> A;
		std::vector<int> B;
		std::vector<int>* newIndex;

		// 二重辺連結成分分解
		// use lowlink http://hos.ac/slides/20110504_graph.pdf
		BiconnectGraph_ DecomposeToBiconnectedComponents(Graph* g)
		{
			this->g = g;
			ord = std::vector<int>(g->getV());
			low = std::vector<int>(g->getV());
			visited = std::vector<bool>(g->getV());
			k = 0;

			A = std::vector<int>(g->getE());
			B = std::vector<int>(g->getE());
			newIndex = new std::vector<int>(g->getV());

			// update ord, low
			dfs(0);

			// update k, A, B, newIndex
			visited.assign(g->getV(), false);
			k = 0;
			(*newIndex)[0] = 0;
			dfs_(0);

			//print();

			return BiconnectGraph_(
				new Graph(k + 1, k, A.data(), B.data()),
				newIndex);
		}

		// Lowlink
		void dfs(int u, int prev = -1)
		{
			visited[u] = true;
			low[u] = ord[u] = k;
			++k;
			for (int i = 0; i < g->getLength(u); ++i)
			{
				int v = g->getEdge(u, i);
				if (!visited[v])
				{
					dfs(v, u);
					low[u] = std::min(low[u], low[v]);
				}
				else if (v != prev)
				{
					low[u] = std::min(low[u], ord[v]);
				}
			}
		}

		// create new graph info
		// change k, A, B, newIndex
		void dfs_(int u)
		{
			visited[u] = true;
			for (int i = 0; i < g->getLength(u); ++i)
			{
				int v = g->getEdge(u, i);
				if (!visited[v])
				{
					assert(ord[u] < ord[v]);
					if (ord[u] < low[v])
					{
						// (u, v) is a bridge
						A[k] = (*newIndex)[u];
						B[k] = (*newIndex)[v] = k + 1;
						k = k + 1;
					}
					else
					{
						(*newIndex)[v] = (*newIndex)[u];
					}
					dfs_(v);
				}
			}
		}

		void print() const
		{
			printf("| ord | low | visited | newIndex |\n");
			for (int i = 0; i < g->getV(); ++i)
			{
				printf("|%4d |%4d |     %3d | %8d |\n", ord[i],
				                                        low[i],
				                                        visited[i],
				                                        (*newIndex)[i]);
			}
		}
	};
};

class BiconnectGraph : private BiconnectGraph_
{
public:
	BiconnectGraph(Graph* g) : BiconnectGraph_(g) {}
	~BiconnectGraph()
	{
		close();
	}

	inline Graph& graph() const
	{
		return *g_;
	}

	inline std::vector<int>& index() const
	{
		return *index_;
	}

	void print()
	{
		graph().print();

		printf("i: reindex\n");
		for (int i = 0; i < index().size(); ++i)
		{
			printf("%d : %d\n", i, index().at(i));
		}
	}
};


class HLDecompositionGraph
{
public:
	std::vector<int> index_to_groupid;
	std::vector<int> index_to_groupindex;
	std::vector<int> groupid_to_parent_groupid;
	std::vector<int> groupid_to_parent_groupindex;
	std::vector<int> groupid_to_size;
	int group_count;

	HLDecompositionGraph(BiconnectGraph* biGraph)
		: index_to_groupid(biGraph->index().size()),
		index_to_groupindex(biGraph->index().size()),
		groupid_to_parent_groupid(biGraph->graph().getV()),
		groupid_to_parent_groupindex(biGraph->graph().getV()),
		groupid_to_size(biGraph->graph().getV())
	{
		Builder builder;
		builder.HLDecompose(this, biGraph);
	}

	void print()
	{
		printf(" i:   gid gindex\n");
		for (int i = 0; i < index_to_groupid.size(); ++i)
		{
			printf("%2d: %5d %5d\n",
				i,
				index_to_groupid[i],
				index_to_groupindex[i]);
		}

		printf("gid:   p_gid p_gindex\n");
		for (int i = 0; i < groupid_to_parent_groupid.size(); ++i)
		{
			printf("%2d: %5d %5d\n",
				i,
				groupid_to_parent_groupid[i],
				groupid_to_parent_groupindex[i]);
		}
	}

	class Builder
	{
	public:
		HLDecompositionGraph* decomposision;
		Graph* g;
		BiconnectGraph* bg;
		// last group id
		int k;
		std::vector<int> depth_;
		std::vector<int> pre_index_to_groupid;
		std::vector<int> pre_index_to_groupindex;
		
		void HLDecompose(HLDecompositionGraph* decomposition, BiconnectGraph* g)
		{
			this->decomposision = decomposition;
			this->g = &g->graph();
			bg = g;
			k = 0;
			depth_ = std::vector<int>(g->graph().getV());
			pre_index_to_groupid = std::vector<int>(g->graph().getV());
			pre_index_to_groupindex = std::vector<int>(g->graph().getV());

			// find deepest node
			//NodeInfo deepest_node = dfs_find_deepest(0);

			// update depth_
			dfs_depth(0);

			// HL decomposition
			dfs_hl_decomposition(0, 0, 0);

			// pre_index to decomposition.index
			for (int i = 0; i < g->index().size(); ++i)
			{
				decomposision->index_to_groupid[i]
					= pre_index_to_groupid[g->index()[i]];
				decomposision->index_to_groupindex[i]
					= pre_index_to_groupindex[g->index()[i]];
			}
			decomposision->group_count = k + 1;
		}

		struct NodeInfo
		{
			int depth;
			int index;
		};

		NodeInfo dfs_find_deepest(int u, int prev = -1)
		{
			NodeInfo info = {0, u};
			for (int i = 0; i < g->getLength(u); ++i)
			{
				int v = g->getEdge(u, i);
				if (v != prev)
				{
					NodeInfo leafInfo = dfs_find_deepest(v, u);
					if (leafInfo.depth > info.depth)
					{
						info = leafInfo;
					}
				}
			}
			++info.depth;
			return info;
		}

		// update depth_
		int dfs_depth(int u, int prev = -1)
		{
			int depth = 0;
			for (int i = 0; i < g->getLength(u); ++i)
			{
				int v = g->getEdge(u, i);
				if (v != prev)
				{
					depth = std::max(depth, dfs_depth(v, u));
				}
			}
			depth_[u] = depth;
			return depth + 1;
		}

		void dfs_hl_decomposition(int u,
			int group_id,
			int group_index,
			int prev = -1)
		{
			pre_index_to_groupid[u] = group_id;
			pre_index_to_groupindex[u] = group_index;
			++decomposision->groupid_to_size[group_id];

			int max_depth = -1;
			int max_depth_index = -1;
			for (int i = 0; i < g->getLength(u); ++i)
			{
				int v = g->getEdge(u, i);
				if (v != prev)
				{
					if (depth_[v] > max_depth)
					{
						max_depth = depth_[v];
						max_depth_index = v;
					}
				}
			}

			for (int i = 0; i < g->getLength(u); ++i)
			{
				int v = g->getEdge(u, i);
				if (v != prev)
				{
					if (v == max_depth_index)
					{
						// Heavy
						dfs_hl_decomposition(v, group_id, group_index + 1, u);
					}
					else
					{
						// Light
						++k;
						decomposision->groupid_to_parent_groupid[k] = group_id;
						decomposision->groupid_to_parent_groupindex[k] = group_index;
						dfs_hl_decomposition(v, k, 0, u);
					}
				}
			}
		}
	};
};

class Solver
{
public:
	using QueType = std::priority_queue<int>;

	HLDecompositionGraph* g;
	std::vector<std::vector<QueType>>* que_list;
	std::vector<SegTree>* seg_list;


	// V : num of vertices
	// E : num of edges
	// vertex[i] = (A[i], B[i])
	Solver(int V, int E, const int A[], const int B[])
	{
		// initialize HLDecompositionGraph
		Graph original_graph(V, E, A, B);
		//original_graph.print();
		BiconnectGraph biconnect_graph(&original_graph);
		//biconnect_graph.print();
		g = new HLDecompositionGraph(&biconnect_graph);
		//g->print();

		// initialize que_list
		que_list = new std::vector<std::vector<QueType>>(g->group_count);
		for (int i = 0; i < g->group_count; ++i)
		{
			(*que_list)[i] = std::vector<QueType>(g->groupid_to_size[i]);
		}

		// initialize seq_list
		seg_list = new std::vector<SegTree>();
		seg_list->reserve(g->group_count);
		for (int i = 0; i < g->group_count; ++i)
		{
			seg_list->emplace_back(g->groupid_to_size[i]);
		}
	}

	void query1(int u, int w)
	{
		int group_id = g->index_to_groupid[u];
		int group_index = g->index_to_groupindex[u];

		(*que_list)[group_id][group_index].push(w);

		auto& seg = (*seg_list)[group_id];
		if (w > seg.data_[group_index])
			seg.update(group_index, w);
	}

	int query2(int s, int t)
	{
		int group_id_0 = g->index_to_groupid[s];
		int group_index_0 = g->index_to_groupindex[s];
		int group_id_1 = g->index_to_groupid[t];
		int group_index_1 = g->index_to_groupindex[t];

		int max_value = -1;
		int group_id_max = -1;
		int group_index_max = -1;

		while (1)
		{
			if (group_id_0 == group_id_1)
			{
				if (group_index_0 > group_index_1)
				{
					std::swap(group_index_0, group_index_1);
				}
				int index;
				int value = (*seg_list)[group_id_0]
					.getmax(group_index_0, group_index_1, &index);
				if (value > max_value)
				{
					max_value = value;
					group_id_max = group_id_0;
					group_index_max = index;
				}
				break;
			}

			if (group_id_0 < group_id_1)
			{
				std::swap(group_id_0, group_id_1);
				std::swap(group_index_0, group_index_1);
			}
			assert(group_id_0 > group_id_1);
			{
				int index;
				int value = (*seg_list)[group_id_0]
					.getmax(group_index_0, &index);
				if (value > max_value)
				{
					max_value = value;
					group_id_max = group_id_0;
					group_index_max = index;
				}
				group_index_0 = g->groupid_to_parent_groupindex[group_id_0];
				group_id_0 = g->groupid_to_parent_groupid[group_id_0];
			}
		}

		if (max_value > 0)
		{
			assert(group_id_max != -1);
			assert(group_index_max != -1);

			// update que
			auto& que = (*que_list)[group_id_max][group_index_max];
			assert(que.top() == max_value);
			que.pop();
			int value;
			if (que.empty())
			{
				value = -1;
			}
			else
			{
				value = que.top();
			}

			// update segtree
			(*seg_list)[group_id_max].update(group_index_max, value);
		}

		return max_value;
	}

	~Solver()
	{
		delete g;
		delete que_list;
		delete seg_list;
	}
};

int N, M, Q;
int A[200000], B[200000];

int main()
{
	scanf("%d %d %d", &N, &M, &Q);
	for (int i = 0; i < M; ++i)
	{
		scanf("%d %d", &A[i], &B[i]);
		--A[i];
		--B[i];
	}

	Solver solver(N, M, A, B);

	for (int i = 0; i < Q; ++i)
	{
		int q, a, b;
		scanf("%d %d %d", &q, &a, &b);
		if (q == 1)
		{
			--a;
			solver.query1(a, b);
		}
		else
		{
			--a;
			--b;
			printf("%d\n", solver.query2(a, b));
		}
	}
}
0