QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#688572 | #2214. Link Cut Digraph | Breakingtdasc | AC ✓ | 576ms | 47296kb | C++14 | 4.0kb | 2024-10-30 11:06:38 | 2024-10-30 11:06:40 |
Judging History
answer
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0,del##i##verme=int(n);i<del##i##verme;++i)
#define rep1(i,n) for(int i=1,parano##i##a=int(n);i<=parano##i##a;++i)
#define per(i,n) for(int i=int(n)-1;i>=0;--i)
#define per1(i,n) for(int i=int(n);i>=1;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define y0 LingLuo
#define y1 VividCycle
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using namespace std;
const ll mod1=998244353;
const ll mod2=1000000007;
unsigned time_related_rand()
{
return unsigned(std::chrono::steady_clock::now().time_since_epoch().count());
}
struct dsu{
ll answer;int cnt;
int p[100005],siz[100005];
int l[100005],r[100005];
void init(int n)
{
answer=0;cnt=0;
rep1(i,n)
{
p[i]=i;siz[i]=1;
}
}
int getp(int x)
{
return (p[x]==x)?x:(getp(p[x]));
}
void merge(int x,int y)
{
x=getp(x);y=getp(y);
if(x==y)
{
l[++cnt]=0;r[cnt]=0;return ;
}
if(siz[x]>siz[y]) swap(x,y);
p[x]=y;answer+=siz[x]*1ll*siz[y];siz[y]+=siz[x];
l[++cnt]=x;r[cnt]=y;
// cout<<"after adding "<<answer<<endl;
}
void revert()
{
if(l[cnt])
{
siz[r[cnt]]-=siz[l[cnt]];p[l[cnt]]=l[cnt];answer-=siz[l[cnt]]*1ll*siz[r[cnt]];
}
--cnt;
// cout<<"after reverting "<<answer<<endl;
}
};
dsu D;
int n,m,u[250005],v[250005];
vector<int> nodes;
ll result[250005];
vector<int> to[100005],fr[100005];
bool vis[100005];int scc[100005],val[100005];int ct;
vector<int> dfn;
void dfs_dfn(int x)
{
vis[x]=true;for(int y:to[x]) if(!vis[y]) dfs_dfn(y);
dfn.pb(x);
}
void dfs_scc(int x,int y)
{
scc[x]=y;for(int z:fr[x]) if(!scc[z]) dfs_scc(z,y);
}
void solve(int l,int r,vector<pair<pair<int,int>,int> > &edges)
{
int m=(l+r)>>1;
// cout<<l<<" ~ "<<r<<endl;
// for(auto P:edges) cout<<P.fi.fi<<" - "<<P.fi.se<<" ("<<P.se<<")"<<endl;
nodes.clear();
for(auto P:edges)
{
nodes.pb(P.fi.fi);nodes.pb(P.fi.se);
}
sort(nodes.begin(),nodes.end());
nodes.erase(unique(nodes.begin(),nodes.end()),nodes.end());
ct=0;dfn.clear();
for(int x:nodes)
{
to[x].clear();fr[x].clear();vis[x]=false;scc[x]=0;
}
for(auto P:edges)
{
if(P.se>m) continue;
to[P.fi.fi].pb(P.fi.se);fr[P.fi.se].pb(P.fi.fi);
}
for(int x:nodes)
{
if(!vis[x]) dfs_dfn(x);
}
reverse(dfn.begin(),dfn.end());
for(int x:dfn)
{
if(!scc[x])
{
dfs_scc(x,++ct);
val[ct]=x;
}
}
// for(int x:nodes) cout<<x<<" scc "<<scc[x]<<endl;
if(l==r)
{
int curt=0;
for(int x:nodes) if(val[scc[x]]!=x)
{
// cout<<x<<" addedge "<<val[scc[x]]<<endl;
++curt;D.merge(x,val[scc[x]]);
}
result[l]=D.answer;
rep(i,curt) D.revert();
// cout<<"revert "<<curt<<endl;
}
else
{
int curt=0;
for(int x:nodes) if(val[scc[x]]!=x)
{
// cout<<x<<" addedge "<<val[scc[x]]<<endl;
++curt;D.merge(x,val[scc[x]]);
}
vector<pair<pair<int,int>,int> > E1,E2;
E1.clear();E2.clear();
for(auto P:edges)
{
if(scc[P.fi.fi]==scc[P.fi.se]) E1.pb(P);
else E2.pb(mp(mp(D.getp(P.fi.fi),D.getp(P.fi.se)),P.se));
}
solve(m+1,r,E2);
rep(i,curt) D.revert();
// cout<<"revert"<<" "<<curt<<endl;
solve(l,m,E1);
}
}
vector<pair<pair<int,int>,int> > edge;
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);
cin>>n>>m;rep1(i,m)cin>>u[i]>>v[i];
D.init(n);rep1(i,m)edge.pb(mp(mp(u[i],v[i]),i));
solve(1,m,edge);
rep1(i,m) cout<<result[i]<<"\n";
return 0;
}
/* things to check
1. int overflow or long long memory need
2. recursion/array/binary search/dp/loop bounds
3. precision
4. special cases(n=1,bounds)
5. delete debug statements
6. initialize(especially multi-tests)
7. = or == , n or m ,++ or -- , i or j , > or >= , < or <=
8. keep it simple and stupid
9. do not delete, use // instead
10. operator priority
11. is there anything extra to output?
12. ...
*/
/* something to think about
1. greedy? dp? searching? dp with matrix/ segment tree? binary search?
2. If contains "not", why not ?????? or few affect?
*/
Details
Test #1:
score: 100
Accepted
time: 564ms
memory: 43540kb
Test #2:
score: 0
Accepted
time: 576ms
memory: 43440kb
Test #3:
score: 0
Accepted
time: 566ms
memory: 43848kb
Test #4:
score: 0
Accepted
time: 534ms
memory: 47108kb
Test #5:
score: 0
Accepted
time: 558ms
memory: 43648kb
Test #6:
score: 0
Accepted
time: 560ms
memory: 44012kb
Test #7:
score: 0
Accepted
time: 560ms
memory: 43164kb
Test #8:
score: 0
Accepted
time: 566ms
memory: 43864kb
Test #9:
score: 0
Accepted
time: 535ms
memory: 47296kb
Test #10:
score: 0
Accepted
time: 554ms
memory: 44368kb
Test #11:
score: 0
Accepted
time: 558ms
memory: 43780kb
Test #12:
score: 0
Accepted
time: 562ms
memory: 43772kb
Test #13:
score: 0
Accepted
time: 534ms
memory: 46804kb
Test #14:
score: 0
Accepted
time: 528ms
memory: 46452kb
Test #15:
score: 0
Accepted
time: 378ms
memory: 37996kb
Test #16:
score: 0
Accepted
time: 514ms
memory: 37912kb
Test #17:
score: 0
Accepted
time: 511ms
memory: 37380kb
Test #18:
score: 0
Accepted
time: 512ms
memory: 37440kb
Test #19:
score: 0
Accepted
time: 559ms
memory: 43736kb
Test #20:
score: 0
Accepted
time: 526ms
memory: 45612kb
Test #21:
score: 0
Accepted
time: 531ms
memory: 45220kb
Test #22:
score: 0
Accepted
time: 531ms
memory: 45048kb
Test #23:
score: 0
Accepted
time: 520ms
memory: 45972kb
Test #24:
score: 0
Accepted
time: 526ms
memory: 45400kb
Test #25:
score: 0
Accepted
time: 519ms
memory: 45540kb
Test #26:
score: 0
Accepted
time: 522ms
memory: 43508kb
Test #27:
score: 0
Accepted
time: 519ms
memory: 43216kb