結果
| 問題 |
No.529 帰省ラッシュ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2017-08-05 07:31:08 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 234 ms / 4,500 ms |
| コード長 | 14,143 bytes |
| コンパイル時間 | 1,534 ms |
| コンパイル使用メモリ | 88,660 KB |
| 実行使用メモリ | 30,824 KB |
| 最終ジャッジ日時 | 2024-12-16 07:31:21 |
| 合計ジャッジ時間 | 5,391 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 18 |
コンパイルメッセージ
In member function 'void SegTree::update(int, int)',
inlined from 'int Solver::query2(int, int)' at main.cpp:684:36:
main.cpp:51:71: warning: 'group_index_max' may be used uninitialized [-Wmaybe-uninitialized]
51 | int value2 = data_[child_begin + (child_index ^ 1)];
| ~~~~~~~~~~~~~^~~~
main.cpp: In member function 'int Solver::query2(int, int)':
main.cpp:619:21: note: 'group_index_max' was declared here
619 | int group_index_max = -1;
| ^~~~~~~~~~~~~~~
ソースコード
#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 = 5
//
// [------6------]
// [--4--] [--5--]
// [0] [1] [2] [3] [4]
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 >= 0 && 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
// Edge[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 nodeIndex) const
{
return length_[nodeIndex];
}
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_lowlink(0);
// update k, A, B, newIndex
visited.assign(g->getV(), false);
k = 0;
(*newIndex)[0] = 0;
dfs_create_graph_info(0);
//print();
return BiconnectGraph_(
new Graph(k + 1, k, A.data(), B.data()),
newIndex);
}
// Lowlink
// gain information (ord, low) for decomposition
void dfs_lowlink(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_lowlink(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_create_graph_info(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_create_graph_info(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() const
{
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() const
{
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 (doesnt make much of difference)
// use this (submission 193255) => 256 ms
// not use (submission 193256) => 256 ms
NodeInfo deepest_node = dfs_find_deepest(0);
// update depth_
dfs_depth(deepest_node.index);
// HL decomposition
dfs_hl_decomposition(deepest_node.index, 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
// Edge[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);
BiconnectGraph biconnect_graph(&original_graph);
g = new HLDecompositionGraph(&biconnect_graph);
//original_graph.print();
//biconnect_graph.print();
//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();
// get que value
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 q[200000], 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];
}
for (int i = 0; i < Q; ++i)
{
scanf("%d %d %d", &q[i], &a[i], &b[i]);
}
Solver solver(N, M, A, B);
for (int i = 0; i < Q; ++i)
{
if (q[i] == 1)
{
solver.query1(a[i] - 1, b[i]);
}
else
{
printf("%d\n", solver.query2(a[i] - 1, b[i] - 1));
}
}
}