QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#106816 | #6127. Kawa Exam | evirir | WA | 2196ms | 42848kb | C++20 | 7.7kb | 2023-05-19 12:54:45 | 2023-05-19 12:54:49 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define sz(x) (int)(x).size()
#define all(x) begin(x), end(x)
#define forn(i,a,b) for(int i=(a);i<(b);i++)
#define fore(i,a,b) for(int i=(a);i<=(b);i++)
#define pb push_back
#define F first
#define S second
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
using Adj = vector<vector<int>>;
vi num, st;
vector<vector<ii>> ed;
vector<ii> edges;
vector<ii> bridges;
int Time;
template<class F>
int dfs_bicomps(int at, int par, F& f) {
int me = num[at] = ++Time, e, y, top = me;
for (auto pa : ed[at]) if (pa.second != par) {
tie(y, e) = pa;
if (num[y]) {
top = min(top, num[y]);
if (num[y] < me)
st.push_back(e);
} else {
int si = sz(st);
int up = dfs_bicomps(y, e, f);
top = min(top, up);
if (up == me) {
st.push_back(e);
f(vi(st.begin() + si, st.end()));
st.resize(si);
}
else if (up < me) st.push_back(e);
else { bridges.push_back(edges[e]); }
}
}
return top;
}
template<class F>
void bicomps(F f) {
num.assign(sz(ed), 0);
forn(i,0,sz(ed)) if (!num[i]) dfs_bicomps(i, -1, f);
}
void reset()
{
num.clear();
st.clear();
ed.clear();
edges.clear();
bridges.clear();
Time = 0;
}
// convert bicomps into nodes, return graph
Adj MakeCompAdj(const int n, const vector<int>& a, vector<vector<ii>>& freq_comp)
{
// make bicomps
vector<int> comp_id(n, -1);
int next_comp_id = 0;
bicomps([&](const vector<int> &edgelist) {
unordered_set<int> node_set;
for (const auto& eid : edgelist)
{
auto [u, v] = edges[eid];
node_set.insert(u);
node_set.insert(v);
}
unordered_map<int, int> cur_count;
for (const int u : node_set)
{
comp_id[u] = next_comp_id;
cur_count[a[u]]++;
}
freq_comp.emplace_back(all(cur_count));
next_comp_id++;
});
// deal with nodes not in a bicomp
forn(i,0,n)
{
if (comp_id[i] == -1)
{
comp_id[i] = next_comp_id++;
freq_comp.emplace_back(vector<ii>{{a[i], 1}});
}
}
// make bicomp graph
Adj comp_adj(next_comp_id);
for (const auto& [u, v] : bridges)
{
int u_comp = comp_id[u];
int v_comp = comp_id[v];
comp_adj[u_comp].pb(v_comp);
comp_adj[v_comp].pb(u_comp);
}
return comp_adj;
}
void dfs(const Adj &adj, const int u, const int p, vector<bool>& vst, vector<int>& cur_tree)
{
vst[u] = true;
cur_tree.push_back(u);
for (const int v : adj[u])
{
if (v == p) continue;
dfs(adj, v, u, vst, cur_tree);
}
}
// group cc's of comp_adj
vector<vector<int>> MakeTrees(const Adj& comp_adj)
{
int comp_cnt = sz(comp_adj);
vector<vector<int>> trees;
vector<int> tree_max_sum;
vector<bool> vst(comp_cnt, false);
forn(i,0,sz(comp_adj))
{
if (vst[i]) continue;
vector<int> cur_tree;
dfs(comp_adj, i, -1, vst, cur_tree);
trees.push_back(cur_tree);
}
return trees;
}
void dfs_euler(Adj &adj, const int u, const int p,
vector<int> &in, vector<int> &out, vector<int>& enode, vector<int>& big, int &tmr,
vector<int>& sz)
{
sz[u] = 1;
in[u] = ++tmr;
enode[tmr] = u;
for (const int v : adj[u])
{
if (v == p) continue;
dfs_euler(adj, v, u, in, out, enode, big, tmr, sz);
if (big[u] == -1 || sz[big[u]] < sz[v]) big[u] = v;
sz[u] += sz[v];
}
forn(i, 0, sz(adj[u]))
{
int v = adj[u][i];
if (sz[v] > sz[adj[u][0]]) swap(adj[u][0], adj[u][i]);
}
out[u] = tmr;
}
class Counter {
private:
unordered_map<int, int> count;
multiset<int> freq_set;
public:
Counter(): count(), freq_set() {}
void add(const int x)
{
if (count[x] != 0)
freq_set.erase(freq_set.find(count[x]));
count[x]++;
freq_set.insert(count[x]);
}
void remove(const int x)
{
assert(count.find(x) != count.end());
freq_set.erase(freq_set.find(count[x]));
count[x]--;
if (count[x] != 0)
freq_set.insert(count[x]);
else
count.erase(x);
}
int most_common() const
{
if (freq_set.empty()) return 0;
return *freq_set.rbegin();
}
};
void add(const int u, const vector<vector<ii>>& freq_comp, Counter& in_sub, Counter& out_sub)
{
for (const auto& [val, c] : freq_comp[u])
{
forn(i,0,c)
{
in_sub.add(val);
out_sub.remove(val);
}
}
}
void remove(const int u, const vector<vector<ii>>& freq_comp, Counter& in_sub, Counter& out_sub)
{
for (const auto& [val, c] : freq_comp[u])
{
forn(i,0,c)
{
in_sub.remove(val);
out_sub.add(val);
}
}
}
void dfs_dsu(const Adj &adj, const vector<vector<ii>>& freq_comp, const vector<int> &in, const vector<int> &out, const vector<int>& enode,
const vector<int>& big, const int u, const int p, const bool keep, Counter& in_sub, Counter& out_sub,
const int base, map<ii, int>& ans)
{
for (const int v : adj[u])
{
if (v == p || v == big[u]) continue;
dfs_dsu(adj, freq_comp, in, out, enode, big, v, u, false, in_sub, out_sub, base, ans);
}
if (big[u] != -1)
{
dfs_dsu(adj, freq_comp, in, out, enode, big, big[u], u, true, in_sub, out_sub, base, ans);
}
for (const int v : adj[u])
{
if (v == p || v == big[u]) continue;
for (int j = in[v]; j <= out[v]; j++)
{
add(enode[j], freq_comp, in_sub, out_sub);
}
}
add(u, freq_comp, in_sub, out_sub);
if (p != -1) ans[{u, p}] = base + in_sub.most_common() + out_sub.most_common();
if (!keep)
{
for (int j = in[u]; j <= out[u]; j++) remove(enode[j], freq_comp, in_sub, out_sub);
}
}
void GetTreeAns(Adj& adj, const vector<vector<ii>>& freq_comp, const vector<int>& nodes, const int base, map<ii, int>& ans,
vector<int>& in, vector<int>& out, vector<int>& enode, vector<int>& big, vector<int>& sz)
{
int rt = nodes[0];
// shared total
Counter in_sub, out_sub;
for (const int u : nodes)
{
for (const auto& [val, c] : freq_comp[u])
{
forn(i,0,c) out_sub.add(val);
}
}
// euler tour
int tmr = -1;
dfs_euler(adj, rt, -1, in, out, enode, big, tmr, sz);
dfs_dsu(adj, freq_comp, in, out, enode, big, rt, -1, false, in_sub, out_sub, base, ans);
}
void AddToMap(const vector<ii>& pairs, unordered_map<int, int>& count)
{
for (const auto& [val, c] : pairs)
{
count[val] += c;
}
}
void solve()
{
reset();
int n, m;
cin >> n >> m;
vector<int> a(n);
forn(i,0,n)
{
cin>>a[i];
a[i]--;
}
// read ori graph
ed.resize(n);
forn(i,0,m)
{
int u,v; cin>>u>>v; u--; v--;
ed[u].emplace_back(v, i);
ed[v].emplace_back(u, i);
edges.pb({u, v});
}
// make bicomp graph
vector<vector<ii>> freq_comp;
Adj comp_adj = MakeCompAdj(n, a, freq_comp);
// make tree groups
vector<vector<int>> trees = MakeTrees(comp_adj);
int tree_cnt = sz(trees);
vector<int> tree_max(tree_cnt);
forn(i, 0, tree_cnt)
{
unordered_map<int, int> cur_cnt;
for (const int u : trees[i])
{
AddToMap(freq_comp[u], cur_cnt);
}
for (const auto &[color, count] : cur_cnt)
{
tree_max[i] = max(tree_max[i], count);
}
}
// process each tree
int max_pre = 0;
int max_suf = accumulate(tree_max.begin() + 1, tree_max.end(), 0);
map<ii, int> ans;
vector<int> in(n), out(n), enode(n), big(n, -1);
vector<int> sz;
sz.resize(n);
forn(i, 0, tree_cnt)
{
int base = max_pre + max_suf;
GetTreeAns(comp_adj, freq_comp, trees[i], base, ans, in, out, enode, big, sz);
max_pre += tree_max[i];
if (i + 1 < tree_cnt) max_suf -= tree_max[i + 1];
}
forn(i,0,sz(edges))
{
if (i > 0) cout << ' ';
ii e = edges[i];
if (ans.find(e) == ans.end()) swap(e.first, e.second);
if (ans.find(e) == ans.end()) cout << max_pre;
else cout << ans[e];
}
cout<<'\n';
}
int main()
{
cin.tie(0)->sync_with_stdio(0);
int t; cin>>t;
fore(i,1,t) solve();
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3540kb
input:
3 7 5 1 2 1 2 1 2 1 1 2 1 3 2 4 5 6 5 7 3 3 1 2 3 1 2 1 3 2 3 2 3 12345 54321 1 2 1 2 1 1
output:
6 5 5 5 4 1 1 1 1 1 1
result:
ok 3 lines
Test #2:
score: -100
Wrong Answer
time: 2196ms
memory: 42848kb
input:
5557 2 7 79960 79960 2 2 1 1 1 1 2 2 1 1 2 1 1 2 9 8 21881 70740 70740 21881 22458 22458 639 21881 70740 3 3 1 6 5 8 7 5 5 7 2 3 5 1 7 6 6 7 13064 20716 6746 13064 6746 69225 5 5 4 1 4 1 1 6 4 5 3 2 3 2 8 4 45146 14400 45146 45146 14400 72969 14400 45146 8 6 1 3 4 6 8 3 18 13 48132 37949 92338 92338...
output:
2 2 2 2 2 2 2 6 6 6 6 6 6 7 6 3 4 4 3 3 3 3 7 7 7 7 8 8 8 8 8 8 8 8 8 9 8 8 8 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 7 8 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 9 9 16 16 16 16 16 17 16 16 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 1...
result:
wrong answer 2nd lines differ - expected: '6 6 7 6 6 6 6 6', found: '6 6 6 6 6 6 7 6'