이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
//#pragma GCC optimize("Ofast,O3")
//#pragma GCC target("avx,avx2")
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#include "debugger.cpp"
#else
#define debug(...)
#endif
template<class T>
int len(T &a){
return a.size();
}
using ll = long long;
using pii = pair<int,int>;
#define all(a) (a).begin(), (a).end()
#define ff first
#define ss second
string fileio = "";
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
const int MOD = 1e9 + 7;
const int inf = 1e9;
const ll infl = 1e18;
const int maxn = 1e5 + 1;
struct DSU{
vector<int> par, sz; int n;
DSU (int _n){
n = _n;
par.resize(n);
iota(all(par), 0);
sz.assign(n, 1);
}
DSU (){}
int get(int a){
return (par[a] == a ? a : par[a] = get(par[a]));
}
void init(int _n){
n = _n;
par.resize(n);
iota(all(par), 0);
sz.assign(n, 1);
}
void unite(int a, int b){
a = get(a);
b = get(b);
if(a == b) return;
if(sz[a] < sz[b]) swap(a,b);
sz[a] += sz[b];
par[b] = a;
}
void link(int a, int b){
a = get(a); b = get(b);
if(a == b) return;
sz[b] += sz[a];
par[a] = b;
}
};
void solve(){
int n, m; cin >> n >> m;
vector<set<int>> half(n), rhalf(n);
vector<set<int>> lead(n);
for(int i = 0; i < n; i ++) lead[i].insert(i);
DSU t(n);
ll ans = 0;
queue<pair<int,int>> q;
auto half_edge = [&](int a, int b){
//debug(a + 1, b + 1);
half[a].insert(b);
rhalf[b].insert(a);
if(half[b].count(a)){
q.push({a, b});
}
};
while(m --){
int a, b; cin >> a >> b; a --; b --;
int la = t.get(a), lb = t.get(b);
if(la == lb || lead[lb].count(a)){
cout << ans << '\n';
continue;
}
lead[lb].insert(a);
half_edge(la, lb);
ans += t.sz[lb];
while(!q.empty()){
tie(a, b) = q.front(); q.pop();
a = t.get(a), b = t.get(b);
if(a == b) continue;
ans += 1ll * t.sz[a] * len(lead[b]) + 1ll * t.sz[b] * len(lead[a]);
if(len(lead[a]) > len(lead[b])) swap(a, b);
t.link(a, b);
for(auto u : lead[a]){
if(lead[b].count(u)) ans -= t.sz[b];
else lead[b].insert(u);
}
lead[a].clear();
half[a].erase(b); half[b].erase(a);
rhalf[b].erase(a); rhalf[a].erase(b);
for(auto i : half[a]){
rhalf[i].erase(b);
half_edge(b, i);
}
for(auto i : rhalf[a]){
half[i].erase(a);
half_edge(i, b);
}
}
cout << ans << '\n';
}
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
auto start = chrono::high_resolution_clock::now();
#ifndef LOCAL
if(fileio.size()){
freopen((fileio + ".in").c_str(), "r", stdin);
freopen((fileio + ".out").c_str(), "w", stdout);
}
#endif
int testcases = 1;
#ifdef Tests
cin >> testcases;
#endif
while(testcases --){
solve();
if(testcases) cout << '\n';
#ifdef LOCAL
else cout << '\n';
cout << "_________________________" << endl;
#endif
}
#ifdef LOCAL
auto duration = chrono::duration_cast<chrono::microseconds>(chrono::high_resolution_clock::now() - start);
cout << "time: " << (double)duration.count()/1000.0 << " milliseconds" << endl;
#endif
return 0;
}
컴파일 시 표준 에러 (stderr) 메시지
joitter2.cpp: In function 'int main()':
joitter2.cpp:138:10: warning: variable 'start' set but not used [-Wunused-but-set-variable]
138 | auto start = chrono::high_resolution_clock::now();
| ^~~~~
joitter2.cpp:141:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
141 | freopen((fileio + ".in").c_str(), "r", stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
joitter2.cpp:142:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
142 | freopen((fileio + ".out").c_str(), "w", stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |