QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#91551 | #6127. Kawa Exam | Lucina | WA | 1ms | 13708kb | C++17 | 6.0kb | 2023-03-29 03:22:33 | 2023-03-29 03:22:35 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
const int nax = 1e5 + 10;
int M;
int n, m;
int a[nax];
array <int, 2> e[nax];
int ans[nax];
int cnt_all[nax];
vector <int> g[nax];
int timer;
int tin[nax];
int low[nax];
vector <int> com;
vector <int> component[nax];
vector <array <int, 2>> tree[nax];
bool is_bridge[nax];
int cur_com = 0;
vector <int> bridges;
int ANS;
int ans_comp[nax];
int get_other(int e_id, int u) {
return e[e_id][0] ^ e[e_id][1] ^ u;
}
array <int, 2> cnt[nax];
int col[nax];
bool vis[nax];
bool vis2[nax];
vector <int> found;
struct Counting {
map <int, int> setik_sub;
int max_freq_sub;
int last_unused;
map <int, int> setik_outer;
map <int, int> keep_freq;
Counting(int last_unused) : max_freq_sub(0), last_unused(last_unused) {}
void add(int k, int v) {
max_freq_sub = max(max_freq_sub, (setik_sub[k] += v));
if (setik_outer.find(k) == setik_outer.end()) {
setik_outer[k] = cnt_all[k];
keep_freq[cnt_all[k]] += 1;
}
auto it = setik_outer.find(k);
keep_freq[it->second] -= 1;
it->second -= v;
keep_freq[it->second] += 1;
}
int update_unused() {
while (last_unused >= 0 && setik_sub.find(cnt[last_unused][0]) != setik_sub.end()) {
last_unused -= 1;
}
if (last_unused >= 0) {
return cnt[last_unused][1];
}
while (!keep_freq.empty()) {
auto it = --keep_freq.end();
if (it->second == 0) keep_freq.erase(it);
else break;
}
return 0;
}
int size() {
return setik_sub.size();
}
int get_ans() {
return max_freq_sub + max(keep_freq.empty() ? 0 : rbegin(keep_freq)->first, update_unused());
}
};
using P = Counting*;
void clear_all() {
timer = 0;
fill(vis, vis + 1 + n, false);
fill(vis2, vis2 + 1 + n, false);
cur_com = 1;
fill(is_bridge, is_bridge + 1 + m, false);
fill(ans, ans + 1 + m, 0);
for (int i = 1 ; i <= n ; ++ i) {
g[i].clear();
component[i].clear();
}
com.clear();
bridges.clear();
}
void dfs(int v, int from_edge) {
vis[v] = true;
low[v] = tin[v] = ++timer;
found.push_back(v);
for (auto e_id : g[v]) {
if (e_id == from_edge) continue;
int to = get_other(e_id, v);
if (!vis[to]) {
dfs(to, e_id);
low[v] = min(low[v], low[to]);
if (low[to] > tin[v]) {
is_bridge[e_id] = true;
bridges.push_back(e_id);
}
} else {
low[v] = min(low[v], tin[to]);
}
}
}
void dfs_assign(int v, int c) {
vis2[v] = true;
col[v] = c;
component[col[v]].push_back(v);
for (int e_id : g[v]) {
if (!is_bridge[e_id]) {
int to = get_other(e_id, v);
if (!vis2[to]) dfs_assign(to, c);
}
}
}
Counting* merge_counting(Counting *x, Counting* y) {
if (x->size() < y->size()) swap(x, y);
for (auto [k, v] : y->setik_sub) {
x->add(k, v);
}
delete y;
return x;
}
Counting* dfs_answer(int v, int from_edge) {
Counting *cur = new Counting(M - 1);
for (int i : component[v]) {
cur->add(a[i], 1);
}
for (auto [to, e_id] : tree[v]) {
if (e_id == from_edge) continue;
Counting *res = dfs_answer(to, e_id);
cur = merge_counting(cur, res);
}
if (from_edge > 0) {
ans[from_edge] += cur->get_ans();
}
return cur;
}
void solve_tree() {
cur_com = 0;
int large_comp = 0;
ANS = 0;
vector <int> all_bridges;
for (int i = 1 ; i <= n ; ++ i) {
if (vis[i]) continue;
large_comp += 1;
bridges.clear();
found.clear();
dfs(i, 0);
M = 0;
vector <int> c;
for (int j : found) c.push_back(a[j]), cnt_all[a[j]] += 1;
sort(begin(c), end(c));
for (int i = 0 ; i < size(c);) {
int j = i;
while (j < size(c) && c[j] == c[i]) j += 1;
cnt[M++] = {c[i], j - i};
i = j;
}
sort(cnt, cnt + M, [](auto &x, auto &y) {
return x[1] < y[1];
});
ans_comp[large_comp] = cnt[M - 1][1];
ANS += ans_comp[large_comp];
cur_com = 0;
for (int z : found) {
if (vis2[z]) continue;
cur_com += 1;
dfs_assign(z, cur_com);
}
for (int e_id : bridges) {
auto [u, v] = e[e_id];
u = col[u], v = col[v];
tree[u].push_back({v, e_id});
tree[v].push_back({u, e_id});
ans[e_id] = -ans_comp[large_comp];
all_bridges.push_back(e_id);
}
Counting * s = dfs_answer(1, 0);
delete s;
for (int i = 1 ; i <= cur_com ; ++ i) {
tree[i].clear();
component[i].clear();
}
for (int j : found) {
cnt_all[a[j]] = 0;
}
}
for (int i = 1 ; i <= m ; ++ i) {
ans[i] += ANS;
}
}
void read() {
cin >> n >> m;
for (int i = 1 ; i <= n ; ++ i) {
cin >> a[i];
com.push_back(a[i]);
}
sort(begin(com), end(com));
com.erase(unique(begin(com), end(com)), end(com));
for (int i = 1 ; i <= n ; ++ i) {
a[i] = lower_bound(begin(com), end(com), a[i]) - begin(com) + 1;
}
for (int i = 1 ; i <= m ; ++ i) {
auto &[u, v] = e[i];
cin >> u >> v;
g[u].push_back(i);
g[v].push_back(i);
}
}
void solve() {
read();
solve_tree();
for (int i = 1 ; i <= m ; ++ i) {
if (i > 1) cout << ' ';
cout << ans[i];
}
cout << '\n';
clear_all();
}
int32_t main() {
int T = 1;
cin.tie(0)->sync_with_stdio(false);
for (cin >> T ; T -- ;) {
solve();
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 1ms
memory: 13708kb
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 5 1 1 1 1 1 1
result:
wrong answer 1st lines differ - expected: '6 5 5 5 4', found: '6 5 5 5 5'