zoukankan      html  css  js  c++  java
  • 杭电多校第八场 HDU6858- Discovery of Cycles(LCT+快读)

    题意:

    给定一个图有m条边,边的序号为1-m,q个强制在线询问(假的强制在线,不过在线能做就是了),每次问第l到第r条边组成的子图是否存在环。

    思路:

    首先每次询问对应的图不一样,要建立一个新图的时间复杂度必然是不够的,考虑先进行预处理。思维一下,一个区间左端点固定了,右端点越大,图上有环的概率越大。实际上,对于一个固定的左端点,如果找出一个最小右端点使子图上有环,那么右端点再往右移也必然有环。因此只要对所有左端点预处理出一个最小的右端点即可O(1)判断给定区间是否可以构成有环的子图。

    如何预处理?思维一下想到了滑动区间,左端点l固定,右端点r一直向右移动,将边加入子图,直到图上可以构成环为止,此时得到pre[l]=r,先不将边r加入图中,将左端点右移一位,即将图上一条边删去,再向右移动右端点,直至图上有环……如此往复,只要进行O(n)次加边和删边的操作,就可以得到所有左端点对应的最小右端点。如何进行删边加边和判断图上有没有环?用LCT即可,若新加入的一条边对应的两个节点的根相同,则加入这条边后图上就会有环(其实这里就是将LCT当成可以删边的并查集进行使用)

    这题读入数据量非常大,有将近1e7个int,可以使用超级快读模板,使用之后快1000ms

    #include <bits/stdc++.h>
    const int maxn=3e5+5;
    using namespace std;
    namespace Fast_IO{ //orz laofu
        const int MAXL((1 << 18) + 1);int iof, iotp;
        char ioif[MAXL], *ioiS, *ioiT, ioof[MAXL],*iooS=ioof,*iooT=ioof+MAXL-1,ioc,iost[55];
        char Getchar(){
            if (ioiS == ioiT){
                ioiS=ioif;ioiT=ioiS+fread(ioif,1,MAXL,stdin);return (ioiS == ioiT ? EOF : *ioiS++);
            }else return (*ioiS++);
        }
        void Write(){fwrite(ioof,1,iooS-ioof,stdout);iooS=ioof;}
        void Putchar(char x){*iooS++ = x;if (iooS == iooT)Write();}
        inline int read(){
            int x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
            if(ioc==EOF)Write(),exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        inline long long read_ll(){
            long long x=0;for(iof=1,ioc=Getchar();(ioc<'0'||ioc>'9')&&ioc!=EOF;)iof=ioc=='-'?-1:1,ioc=Getchar();
            if(ioc==EOF)Write(),exit(0);
            for(x=0;ioc<='9'&&ioc>='0';ioc=Getchar())x=(x<<3)+(x<<1)+(ioc^48);return x*iof;
        }
        void Getstr(char *s, int &l){
            for(ioc=Getchar();ioc==' '||ioc=='
    '||ioc=='	';)ioc=Getchar();
            if(ioc==EOF)Write(),exit(0);
            for(l=0;!(ioc==' '||ioc=='
    '||ioc=='	'||ioc==EOF);ioc=Getchar())s[l++]=ioc;s[l] = 0;
        }
        template <class Int>void Print(Int x, char ch = ''){
            if(!x)Putchar('0');if(x<0)Putchar('-'),x=-x;while(x)iost[++iotp]=x%10+'0',x/=10;
            while(iotp)Putchar(iost[iotp--]);if (ch)Putchar(ch);
        }
        void Putstr(const char *s){for(int i=0,n=strlen(s);i<n;++i)Putchar(s[i]);}
    } // namespace Fast_IO
    using namespace Fast_IO;
    namespace LCT {
        struct node {
            int f, son[2] ;
            bool fz ;
        } tr[maxn] ;
        inline void init(int n){
            for(int i=0;i<=n;i++)
                tr[i].f=tr[i].son[0]=tr[i].son[1]=tr[i].fz=0;
        }
        inline void reverse ( int x ) {
            tr[x].fz = 0 ;
            swap ( tr[x].son[0], tr[x].son[1] ) ;
            int lc = tr[x].son[0] ;
            int rc = tr[x].son[1] ;
            tr[lc].fz ^= 1, tr[rc].fz ^= 1 ;
        }
        inline void rotate ( int x, int w ) {
            int f = tr[x].f, ff = tr[f].f, r, R ;
            r = tr[x].son[w] ;
            R = f ;
            tr[R].son[1-w] = r ;
            if ( r )
                tr[r].f = R ;
            r = x ;
            R = ff ;
            if ( tr[R].son[0] == f )
                tr[R].son[0] = r ;
            else if ( tr[R].son[1] == f )
                tr[R].son[1] = r ;
            tr[r].f = R ;
            r = f ;
            R = x ;
            tr[R].son[w] = r ;
            tr[r].f = R ;
        }
        int tmp[maxn] ;
        inline void splay ( int x, int rt ) {
            int s = 0, i = x ;
            while ( tr[i].f && (tr[tr[i].f].son[0]==i||tr[tr[i].f].son[1]==i) ) {
                tmp[++s] = i ;
                i = tr[i].f ;
            }
            tmp[++s] = i ;
            while ( s ) {
                i = tmp[s] ;
                s -- ;
                if ( tr[i].fz )
                    reverse(i) ;
            }
            while ( tr[x].f!=rt && (tr[tr[x].f].son[0]==x||tr[tr[x].f].son[1]==x) ) {
                int f = tr[x].f, ff = tr[f].f ;
                if ( ff == rt || (tr[ff].son[0]!=f&&tr[ff].son[1]!=f) ) {
                    if ( x == tr[f].son[0] )
                        rotate(x,1) ;
                    else
                        rotate(x,0) ;
                } else {
                    if ( tr[ff].son[0] == f && tr[f].son[0] == x )
                        rotate(f,1), rotate(x,1) ;
                    else if ( tr[ff].son[1] == f && tr[f].son[1] == x )
                        rotate(f,0), rotate(x,0) ;
                    else if ( tr[ff].son[0] == f && tr[f].son[1] == x )
                        rotate(x,0), rotate(x,1) ;
                    else if ( tr[ff].son[1] == f && tr[f].son[0] == x )
                        rotate(x,1), rotate(x,0) ;
                }
            }
        }
        inline void access ( int x ) {
            int y = 0 ;
            while ( x ) {
                splay ( x, 0 ) ;
                tr[x].son[1] = y ;
                if ( y != 0 )
                    tr[y].f = x ;
                y = x ;
                x = tr[x].f ;
            }
        }
        inline void makeroot ( int x ) {
            access(x) ;
            splay(x,0) ;
            tr[x].fz ^= 1 ;
        }
        inline void link ( int x, int y ) {
            makeroot(x) ;
            tr[x].f = y ;
            access(x) ;
        }
        inline void cut ( int x, int y ) {
            makeroot(x) ;
            access(y) ;
            splay(y,0) ;
            tr[tr[y].son[0]].f = 0 ;
            tr[y].son[0] = 0 ;
        }
        int find_root ( int x ) {
            access(x) ;
            splay(x,0) ;
            while ( tr[x].son[0] != 0 )
                x = tr[x].son[0] ;
            return x ;
        }
    }
    using namespace LCT;
    int u[maxn],v[maxn];
    int pre[maxn];
    int main () {
        int T;
        T=read();
        while(T--){
            int n,m,q;
            n=read();
            m=read();
            q=read();
            init(m);
            memset(pre,0,sizeof(int)*(m+1));
            for(int i=1;i<=m;i++){
                u[i]=read();
                v[i]=read();
            }
            int p=1;
            for(int i=1;i<=m;i++){
                if(i>1){
                    cut(u[i-1],v[i-1]);
                }
                for(p;p<=m;p++){
                    if(find_root(u[p])!=find_root(v[p])){
                        link(u[p],v[p]);
                    }
                    else{
                        pre[i]=p;
                        break;
                    }
                }
            }
            int lastans=0;
            for(int i=1;i<=q;i++){
                int l1,r1;
                l1=read();
                r1=read();
                int k1=(l1^lastans)%m+1;
                int k2=(r1^lastans)%m+1;
                l1=min(k1,k2);
                r1=max(k1,k2);
                if(pre[l1] && r1>=pre[l1]){
                    lastans=1;
                    puts("Yes");
                }
                else{
                    lastans=0;
                    puts("No");
                }
            }
        }
    }
    

    参考与引用: https://jkchen.blog.csdn.net/article/details/107991684

  • 相关阅读:
    Oracle数据库学习(四)
    近期整理
    2020/5/29
    2020/5/26
    2020/5/25
    2020/5/22
    2020/5/16
    2020/5/15
    2020/5/14
    2020/5/13
  • 原文地址:https://www.cnblogs.com/ucprer/p/13501715.html
Copyright © 2011-2022 走看看