ACM-ICPC Beijing Division 2017 Network Synchronized Competition C

http://hihocoder.com/contest/icpcbeijing2017/problem/3

Union search with undo + Mo team

The complexity of Kouhu Yibo, for the time being, it is considered that the merging and revocation of the merged set are O(1)

Considering offline query, Mo team handles it. For a query that is all in the block, the solution is directly violent, and the solution is sqrt(n) once.

Then start to enumerate the block where the left endpoint is located, first sort the right endpoint, the right endpoint in the block is incremented, the query at this time is like this, the left endpoint is at [a1, a2] The right endpoint is at [a2+1, n], We consider such an edge, u, v. If uv is in [a2+1,n], there is no need to cancel it, because it will be used later. For the edge where u is in [a1,a2], this needs to be canceled. , so each time we maintain [a2+1, lastr] lastr is the r of the previous query, the next query r is larger than the previous one, and then violently maintain the left side (the edge to be revoked). The complexity is calculated like this. For an edge, there are only two cases to be enumerated. At this time, the left block of the enumeration contains the left breakpoint, so the number of times of enumeration is the number of queries where the left block is located, and the second The kind is that the left block of the enumeration does not contain the left endpoint, so that it is enumerated at most once, and the number of times each edge is enumerated is sqrt(m) (mouth hu);

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
using namespace std;
typedef long long int lll;
namespace Solve {
    lll n,m,q;
    11 years old;
    const lll maxn = 55009;
    lll fa [maxn], si [maxn];
    lll lef[maxn*2],rig[maxn*2];
    lll anss[maxn*2];
    vector<lll> modui[1009];
    lll block;
    stack< pair<lll *,lll > > stak;
    vector<lll> vv1[maxn];
    void init(){
        years = 0;
        for(lll i=0;i<maxn;i++){
            fa [i] = i;
            si [i] = 1;
            vv1[i].clear();
        }
        for(lll i=0;i<1009;i++){
            modui[i].clear();
        }
        while (!stak.empty()) {
            stak.pop ();
        }
        years = 0;
        block = 0;
    }
    lll find(lll x){
        while (fa[x]!=x) {
            x = fa [x];
        }
        return x;
    }
    void uni(lll u,lll v,bool on){
        u = find(u);
        v = find (v);
        if(u==v) return ;
        if(si[u]<si[v]) swap(u,v);
        if(on) stak.push({&fa[v],fa[v]});
        fa [v] = u;
        if(on) stak.push({&ans,ans});
        ans- = if [u] * (if [u] -1) / 2;
        ans- = si [v] * (si [v] -1) / 2;
        if(on) stak.push({&si[u],si[u]});
        si [u] + = si [v];
        ans + = si [u] * (si [u] -1) / 2;
    }
    void back(){
        while (!stak.empty()) {
            * stak.top (). first = stak.top (). second;
            stak.pop ();
        }
    }
    void solve(){
        init();
        scanf("%lld%lld%lld",&n,&m,&q);
        block = sqrt(n);
        for(lll i=1;i<=m;i++){
            lll u,v;
            scanf("%lld%lld",&u,&v);
            vv1[u].push_back(v);
            vv1[v].push_back(u);
        }
        for(lll i=1;i<=q;i++){
            scanf("%lld%lld",&lef[i],&rig[i]);
            lll lb = (lef[i]-1)/block,rb =(rig[i]-1)/block;
            if(lb==rb){
                lll tmp = lef[i];
                while (tmp<=rig[i]) {
                    for(lll v : vv1[tmp])if(v<=rig[i]&& v>=lef[i]){
                        uni(tmp, v, true);
                    }
                    tmp++;
                }
                anss[i] = ans;
                back();
            }else{
                modui[lb].push_back(i);
            }
        }
        for(lll i=0;(i+1)*block<=n;i++){
            sort(modui[i].begin(), modui[i].end(), [](lll a,lll b){ return rig[a]<rig[b];});
            years = 0;
            while (!stak.empty()) {
                stak.pop ();
            }
            for(lll i=1;i<=n;i++){
                fa [i] = i;
                si [i] = 1;
            }
            lll tl = (i+1)*block;
            lll tr = tl-1;
            for(lll j :modui[i]){
                while (tr<rig[j]) {
                    tr++;
                    for(lll v:vv1[tr]) if(v<=tr && v>=tl){
                        uni (tr, v, false);
                    }
                }
                while (tl>lef[j]) {
                    tl--;
                    for(lll v:vv1[tl]) if(v<=tr && v>=tl){
                        uni (tl, v, true);
                    }
                }
                anss[j] = ans;
                back();
                tl = (i+1)*block;
            }
            
        }
        for(lll i=1;i<=q;i++){
            printf("%lld\n",anss[i]);
        }
    }
}
int main(int argc, const char * argv[]) {
    lll T;
    scanf("%lld",&T);
    while (T--) {
        Solve::solve();
    }
    return 0;
}

  

 
 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324599286&siteId=291194637