이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
typedef int us;
typedef long long ll;
typedef pair<us,us> ii;
typedef vector<int> vi;
int C = 650;
ii L[1000001];
int par[51111];
int curcnt=0;
void init()
{
memset(par,-1,sizeof(par));
curcnt=0;
}
us rt(us u, us ty=0)
{
if(par[u]<0) return u;
else
{
if(ty) return (par[u]=rt(par[u]));
else return rt(par[u]);
}
}
void merge(us u, us v, us ty=0)
{
u=rt(u,ty); v=rt(v,ty);
if(u==v) return ;
// if(par[u]==par[v]&&(rand()%2==0)) swap(u,v);
if(par[u]>par[v]) swap(u,v);
// par[u] must be negative, and enforcing par[u] <= par[v] ensures par[u] has bigger size
L[curcnt++] = {v,-par[v]};
par[u]+=par[v];
// par[v] is now positive, and this value is used for rollback and traversing
// par[] stores size of component for representative, stores parent for non-representative
// if par[i] < 0, i is a representative with component size of -par[i]
par[v]=u;
}
void rollback()
{
int cc=curcnt-1;
int u=par[L[cc].fi];
par[u]+=L[cc].se;
par[L[cc].fi]=-L[cc].se;
curcnt--;
}
ii E[121311];
int W[121311];
int ans[121311];
pair<int,pair<int,int> > queries[123231];
vector<pair<int,pair<ii,ii> > > edges;
int n,m;
void update(int l, int r)
{
for(int i=l;i<=r;i++)
{
if(queries[i].fi==1)
{
int lab=queries[i].se.fi; int w=queries[i].se.se;
W[lab]=w;
}
}
}
void solve(int l, int r)
{
// vector<pair<update time or id,pair<bridge id,new weight> > > UD;
vector<pair<int,pair<int,int> > > UD;
// vector<id of bridge in order of updates>
vi bad;
for(int i=l;i<=r;i++) // O(sqrt(q))
{
if(queries[i].fi==1)
{
// lab is bridge id
int lab=queries[i].se.fi; int w=queries[i].se.se;
bad.pb(lab);
UD.pb({i,{lab,w}});
}
}
vector<pair<int,pair<int,int> > > Q;
for(int i=l;i<=r;i++) // O(sqrt(q))
{
if(queries[i].fi==2)
{
int u=queries[i].se.fi; int w=queries[i].se.se;
Q.pb({w,{u,i}});
}
}
sort(Q.rbegin(),Q.rend()); // O(sqrt(q log q))
int ptr=0;
// start new DSU structure
init(); // O(n)
for(int i=0;i<Q.size();i++)// O(sqrt(q))
{
// process query from heaviest car
int w=Q[i].fi; int u=Q[i].se.fi; int lab=Q[i].se.se;
// for all bridges with ok previous weight limit
while(ptr<edges.size()&&edges[ptr].fi>=w) // O(q+m) directly to solve(), not nested in upper for loop
{
// if time of last update is less than l and time of the described update is greater than r
// i.e. this update doesn't occur during time bucket
// i.e. no update of this bridge occurs during time bucket
// updates before have already been committed
// updates after time bucket is of no concern
if(edges[ptr].se.se.fi<=l&&edges[ptr].se.se.se>=r)
// merge the nodes mentioned in edges[ptr] with path compression
// these will not be rolled back
merge(edges[ptr].se.fi.fi,edges[ptr].se.fi.se,1); // O(log n)
ptr++;
}
vector<pair<int,int> > upd;
int pt=0;
// for all updates in time bucket happening before the query
while(pt<UD.size()&&UD[pt].fi<=lab) // O(sqrt(q))
{
int lab=UD[pt].se.fi; int w=UD[pt].se.se;
// store state before modification
// these states will be reverted since queries are processed offline
upd.pb({lab,W[lab]});
W[lab]=w;
pt++;
}
// mark current version id, will rollback to this state
int curl=curcnt;
// for all updates in time bucket
// x is bridge id
for(int x:bad) // O(sqrt(q))
{
int u=E[x].fi; int v=E[x].se; int ww=W[x];
// w is car weight
// if the updated bridge limit is ok for car
if(w<=ww)
{
// these merges will be rolled back (no path compression)
merge(u,v);
}
}
ans[lab]=-par[rt(u)];
while(curcnt>curl) rollback(); // O(sqrt(q))
reverse(upd.begin(),upd.end()); // O(sqrt(q))
for(auto t:upd) W[t.fi]=t.se; // O(sqrt(q))
}
// commit all updates in time bucket
update(l,r); // O(sqrt(q))
}
int las[111111];
int preW[111111];
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0);
cin>>n>>m;
memset(ans,-1,sizeof(ans));
for(int i=0;i<m;i++)
{
int u,v,w; cin>>u>>v>>w; u--; v--;
E[i]=mp(u,v); W[i]=preW[i]=w;
}
int q; cin>>q;
int q1=0;
for(int i=0;i<q;i++) // O(q)
{
int a,b,c; cin>>a>>b>>c; b--;
if(a==1)
{
if(las[b]<=i-1) edges.pb({preW[b],{{E[b].fi,E[b].se},{las[b],i-1}}});
las[b]=i; preW[b]=c;
}
queries[i]={a,{b,c}};
}
for(int i=0;i<m;i++) // O(m)
{
if(las[i]<=q-1)
{
edges.pb({preW[i],{{E[i].fi,E[i].se},{las[i],q-1}}});
}
}
sort(edges.rbegin(),edges.rend()); // O( (m+q) log (m+q) )
int l=0; int r=0;
// O(q) loop
// calls solve for O(sqrt(q)) times
while(r<q)
{
if(queries[r].fi==1) q1++;
// C is sqrt(n)
if(q1>=C)
{
solve(l,r);
l=r+1;
q1=0;
}
r++;
}
if(l<q) solve(l,q-1);
for(int i=0;i<q;i++)
{
if(ans[i]!=-1) cout<<ans[i]<<'\n';
}
}
컴파일 시 표준 에러 (stderr) 메시지
bridges.cpp: In function 'void solve(int, int)':
bridges.cpp:108:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::pair<int, int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
108 | for(int i=0;i<Q.size();i++)// O(sqrt(q))
| ~^~~~~~~~~
bridges.cpp:113:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::pair<std::pair<int, int>, std::pair<int, int> > > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
113 | while(ptr<edges.size()&&edges[ptr].fi>=w) // O(q+m) directly to solve(), not nested in upper for loop
| ~~~^~~~~~~~~~~~~
bridges.cpp:129:17: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::pair<int, int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
129 | while(pt<UD.size()&&UD[pt].fi<=lab) // O(sqrt(q))
| ~~^~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |