Submission #211895

#TimeUsernameProblemLanguageResultExecution timeMemory
211895mieszko11bMaking Friends on Joitter is Fun (JOI20_joitter2)C++14
100 / 100
778 ms41720 KiB
#include <bits/stdc++.h> using namespace std; using ii = pair<int, int>; #define X first #define Y second using ll = long long; int n, m; int p[100007], ran[100007]; set<ii> GID[100007]; set<int> GO[100007]; ll res = 0; void init() { for(int i = 1 ; i <= n ; i++) { p[i] = i; ran[i] = 1; } } int Find(int a) { if(p[a] == a) return a; return p[a] = Find(p[a]); } void remove_between(int a, int b) { set<ii>::iterator it; while((it = GID[b].lower_bound({a, 0})) != GID[b].end() && it->X == a) { //~ cout << "x" << endl; res -= ran[b]; GID[b].erase(it); GO[a].erase(b); } } void print_all() { cout << "res is " << res << endl; for(int i = 1 ; i <= n ; i++) cout << "rep of "<< i << " is "<<Find(i) << endl; for(int i = 1 ; i <= n ; i++) { if(i == Find(i)) { cout << "AAA " <<i << endl; cout << "OUT: "; for(int x : GO[i]) cout << x << " "; cout << endl; cout << "IN: "; for(ii x : GID[i]) cout << "(" << x.X << ","<<x.Y <<") "; cout << endl; } } } void Union(int a, int b) { a = Find(a); b = Find(b); //~ cout << "Union " << a << " " << b << endl; //~ cout << "at the beginning:" << endl; //~ print_all(); if(a == b) return ; if(ran[a] < ran[b]) swap(a, b); remove_between(a, b); //~ cout << "x" << endl; remove_between(b, a); //~ cout << "after edge removal:" << endl; //~ print_all(); //~ cout << "x" << endl; vector<int> to_union; for(int x : GO[b]) { auto it = GID[x].lower_bound({b, 0}); while((it = GID[x].lower_bound({b, 0})) != GID[x].end() && it->X == b) { auto p = *it; GID[x].erase(it); GID[x].insert({a, p.Y}); } GO[a].insert(x); if(GO[x].count(a)) to_union.push_back(x); } GO[b].clear(); res += (ll)ran[b] * GID[a].size(); for(auto p : GID[b]) { GO[p.X].erase(b); GO[p.X].insert(a); if(!GID[a].count(p)) { res += ran[a]; GID[a].insert(p); } else res -= ran[b]; if(GO[a].count(p.X)) to_union.push_back(p.X); } GID[b].clear(); res -= (ll)ran[a] * (ran[a] - 1); res -= (ll)ran[b] * (ran[b] - 1); res += ll(ran[a] + ran[b]) * (ran[a] + ran[b] - 1); p[b] = a; ran[a] += ran[b]; for(int x : to_union) Union(a, x); } void add_edge(int a, int b) { int wa = a; a = Find(a); b = Find(b); if(a == b) return ; if(!GID[b].count({a, wa})) { res += ran[b]; GID[b].insert({a, wa}); GO[a].insert(b); } if(GO[a].count(b) && GO[b].count(a)) Union(a, b); } int main() { scanf("%d%d", &n, &m); init(); for(int i = 0 ; i < m ; i++) { int a, b; scanf("%d%d", &a, &b); add_edge(a, b); printf("%lld\n", res); //~ print_all(); } return 0; }

Compilation message (stderr)

joitter2.cpp: In function 'int main()':
joitter2.cpp:145:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d", &n, &m);
  ~~~~~^~~~~~~~~~~~~~~~
joitter2.cpp:149:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d%d", &a, &b);
   ~~~~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...