QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#91544 | #6127. Kawa Exam | Lucina | WA | 1140ms | 40184kb | C++20 | 6.0kb | 2023-03-29 03:08:28 | 2023-03-29 03:08:29 |
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;
multiset <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.insert(cnt_all[k]);
}
auto it = setik_outer.find(k);
keep_freq.erase(keep_freq.find(it->second));
it->second -= v;
keep_freq.insert(it->second);
}
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];
}
return 0;
}
int size() {
return setik_sub.size();
}
int get_ans() {
return max_freq_sub + (*keep_freq.rbegin(), update_unused());
}
};
/**
We need data structure that use O(L)?
We probably want to advanced pointer, largest not in set and
deadvanced in backward
*/
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();
}
}
詳細信息
Test #1:
score: 100
Accepted
time: 1ms
memory: 11732kb
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: 1140ms
memory: 40184kb
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 7 6 6 5 6 6 3 3 3 4 4 3 3 4 6 5 5 9 9 9 8 9 8 9 8 9 9 10 9 9 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 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 9 10 9 15 16 16 14 16 17 16 15 10 10 11 9 12 11 10 10 10 10 10 10 10 12 10 10 10 10 10 11 10 9 9 9 9 7 9 9 9 9 9 9 8 9 10 7...
result:
wrong answer 2nd lines differ - expected: '6 6 7 6 6 6 6 6', found: '6 6 7 6 6 5 6 6'