제출 #596649

#제출 시각아이디문제언어결과실행 시간메모리
596649Bench0310이상적인 도시 (IOI12_city)C++17
100 / 100
488 ms56516 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1000000000; int add(int a,int b){return a+b-(a+b>=mod?mod:0);} int mul(int a,int b){return (ll(a)*b)%mod;} int res=0; const int N=100000; int n; vector<array<int,2>> tree[4*N]; vector<vector<array<int,2>>> upd(4*N); int p[N]; int sz[N]; int events=0; int find_set(int a) { if(a==p[a]) return a; else return find_set(p[a]); } //~ void dsu_state() //~ { //~ cout << "DSU state: "; //~ map<int,vector<int>> m; //~ for(int i=0;i<n;i++) m[find_set(i)].push_back(i); //~ cout << "groups(" << m.size() << "):" << endl; //~ for(auto [u,v]:m) //~ { //~ for(int x:v) cout << x << " "; //~ cout << "actual_size=" << v.size() << ", sz=" << sz[u] << endl; //~ } //~ cout << endl; //~ } void merge_sets(int a,int b,vector<array<int,2>> &u) { a=find_set(a); b=find_set(b); if(a==b) return; if(sz[a]<sz[b]) swap(a,b); //~ cout << "about to merge [" << a << "," << b << "], before:"; //~ dsu_state(); u.push_back({b,p[b]}); u.push_back({a,sz[a]}); p[b]=a; sz[a]+=sz[b]; //~ cout << "after:"; //~ dsu_state(); } void apply(int idx,int l,int r,int ql,int qr,int a,int b) { if(ql>qr) return; if(l==ql&&r==qr) tree[idx].push_back({a,b}); else { int m=(l+r)/2; apply(2*idx,l,m,ql,min(qr,m),a,b); apply(2*idx+1,m+1,r,max(ql,m+1),qr,a,b); } } void process(int idx,int l,int r) { //~ cout << "idx merges[" << idx << "]: l=" << l << ", r=" << r << ": "; for(auto [a,b]:tree[idx]) { merge_sets(a,b,upd[idx]); //~ cout << "[" << a << "," << b << "] "; } //~ cout << endl; //~ if(l==r) //~ { //~ cout << "after entering and processing tree[" << l << "," << r << "]: "; //~ dsu_state(); //~ } if(l<r) { int m=(l+r)/2; process(2*idx,l,m); process(2*idx+1,m+1,r); } else { //~ cout << "event #" << l << ": " << sz[find_set(0)] << endl; res=add(res,mul(sz[find_set(0)],n-sz[find_set(0)])); } reverse(upd[idx].begin(),upd[idx].end()); for(int i=0;i<(int)upd[idx].size();i++) ((i&1)?p:sz)[upd[idx][i][0]]=upd[idx][i][1]; } void go(int *X,int *Y) { vector<array<int,2>> blocks(n); for(int i=0;i<n;i++) blocks[i]={X[i],Y[i]}; for(int i=0;i<n;i++) { p[i]=i; sz[i]=1; } events=0; map<array<int,2>,int> m; for(int i=0;i<n;i++) m[{X[i],Y[i]}]=i; auto id=[&](int x,int y) { if(m.find({x,y})!=m.end()) return m[{x,y}]; else return -1; }; vector<array<int,4>> v; for(int i=0;i<n;i++) { int t=id(X[i]+1,Y[i]); if(t!=-1) v.push_back({X[i],Y[i],i,t}); int j=id(X[i],Y[i]+1); if(j!=-1) merge_sets(i,j,upd[0]); } sort(v.begin(),v.end()); int len=v.size(); vector<array<int,2>> groups; int l=0; while(l<len) { int r=l; while(r+1<len&&v[r+1][0]==v[l][0]&&v[r][1]+1==v[r+1][1]) r++; groups.push_back({l,r}); events++; l=r+1; } for(int i=1;i<=events;i++) { //~ cout << "group " << i << ": "; auto [one,two]=groups[i-1]; for(int j=one;j<=two;j++) { //~ cout << "[" << v[j][2] << "," << v[j][3] << "] "; if(i-1>=1) apply(1,1,events,1,i-1,v[j][2],v[j][3]); if(i+1<=events) apply(1,1,events,i+1,events,v[j][2],v[j][3]); } //~ cout << endl; } process(1,1,events); //spring cleaning for(int i=0;i<4*N;i++) { tree[i].clear(); upd[i].clear(); } } int DistanceSum(int _n,int *x,int *y) { n=_n; go(x,y); go(y,x); return res; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...