Submission #264187

#TimeUsernameProblemLanguageResultExecution timeMemory
264187jeqcho다리 (APIO19_bridges)C++17
44 / 100
3090 ms9576 KiB
#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;
int const M=1e5;
int const N=5e4;
int const Q=1e5;

int par[N];

void init()
{
    memset(par,-1,sizeof(par));
}

us rt(us u)
{
    if(par[u]<0) return u;
    return (par[u]=rt(par[u]));
}

void merge(us u, us v)
{
    u=rt(u); v=rt(v);
    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
    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;
}


ii E[M];
int W[M];
int ans[Q];
pair<int,pair<int,int> > queries[Q];
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;
        }
    }
}

bitset<N> vis;
vi adj[N];

int dfs(us u)
{
    if(vis[u])return 0;
    vis[u]=1;
    int cand = -par[u];
    for(auto v: adj[u])
    {
        cand += dfs(v);
    }
    return cand;
}

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;
    vector<pair<int,pair<int,int> > > Q;
    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}});
        }
        else
        {
            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); // 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
        // for all updates in time bucket
        // x is bridge id
        vi xtra;
        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)
            {
                // here change to dfs
                int rtu = rt(u);
                int rtv = rt(v);
                adj[rtu].pb(rtv);
                adj[rtv].pb(rtu);
                xtra.pb(rtu);
                xtra.pb(rtv);
            }
        }
        int rep = rt(u);
        ans[lab] = dfs(rep);
        reverse(upd.begin(),upd.end()); // O(sqrt(q))
        for(auto t:upd) W[t.fi]=t.se; // O(sqrt(q))
        for(auto t:xtra)
        {
            adj[t].clear();
            vis[t]=0;
        }
        vis[rep]=0;
    }
    // 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],{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],{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';
    }
}

Compilation message (stderr)

bridges.cpp: In function 'void solve(int, int)':
bridges.cpp:107: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]
  107 |     for(int i=0;i<Q.size();i++)// O(sqrt(q))
      |                 ~^~~~~~~~~
bridges.cpp:112: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]
  112 |         while(ptr<edges.size()&&edges[ptr].fi>=w) // O(q+m) directly to solve(), not nested in upper for loop
      |               ~~~^~~~~~~~~~~~~
bridges.cpp:128: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]
  128 |         while(pt<UD.size()&&UD[pt].fi<=lab) // O(sqrt(q))
      |               ~~^~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...