zoukankan      html  css  js  c++  java
  • 7.19T3

    小 X 的图
    题目背景及题意
    小 X 有一张图,有 n 个点(从 0 开始编号),一开始图里并没有
    边,他有时候会向其中添加一条双向边(x 到 y)。小 X 会时不时想知
    道某两个点是否联通,如果连通并在 t 次加边操作之前不连通,他就
    会对自己加的边感到满意,否则他就会生气,并会错误地记录接下来
    添加的边,将 x 记录为(x+n-c)%n ,y 记录为(y+n-c)%n。直到
    他下一次询问为止。C 是一个小 X 随意定的值(一开始是 0),当然也
    会随他意愿修改。
    你的任务就是回答他的每一次询问
    输入格式
    第一行 n,m,表示点的个数和小 X 操作的总数
    接下来 m 行,每行先是一个字符
    “K”:接下来一个数字 c,表示小 X 新的 c 值
    “R”:接下来两个整数 u,v,表示连一条双向边
    “T”:接下来三个整数 u,v,t,表示询问 u 到 v 的连通性,t 的意
    义上文已经提到过了
    保证:无自环(但有重边
    输出格式
    对于每个询问输出一行“Y”代表小 X 满意,“N”代表小 X 生气
    样例数据 详见 sample 文件夹
     
    数据范围
    对于 30%的数据 n<=1000,m<=3000
    对于剩余数据:n , m<=300000
    对于所有数据:0<=t<=m(但有可能向前第 t 次加边不存在
    提示:做完这题你就 AK 了,是不是很开心呢
     
    sol:这大概就是一道可持久化并查集裸题。虽然300000两只log看上去有点不可过,但就是过了。。。
    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0; bool f=0; char ch=' ';
        while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
        while(isdigit(ch)) {s=(s<<3)+(s<<1)+(ch^48); ch=getchar();}
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0) {putchar('-'); x=-x;}
        if(x<10) {putchar(x+'0'); return;}
        write(x/10); putchar((x%10)+'0');
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=300005;
    inline void copy(int &x,int y,int l,int r);
    inline void Build(int &x,int l,int r);
    inline void Chag(int &x,int y,int l,int r,int Pos,int Val);
    inline int Que(int x,int l,int r,int Pos);
    int n,m,cnt=0,Now;
    int fa[N],sz[N];
    vector<int>Jh[N];
    int rt[N<<2];
    #define PB push_back
    struct Node
    {
        int ls,rs,id;
    }T[N*105];
    inline int gf(int x){return (x==fa[x])?(x):(fa[x]=gf(fa[x]));}
    inline void ubbon(int x,int y)
    {
        int i,xx=gf(x),yy=gf(y);
        if(xx==yy)
        {
    //        cout<<"@@@@@"<<x<<' '<<y<<endl;
            copy(rt[Now],rt[Now-1],1,n); return;
        }
        if(sz[xx]<sz[yy]) swap(xx,yy);
        fa[yy]=xx; sz[xx]+=sz[yy];
        int oo[2],t=0; copy(oo[t],rt[Now-1],1,n);
        for(i=0;i<Jh[yy].size();i++)
        {
            t^=1; oo[t]=0;
            Chag(oo[t],oo[t^1],1,n,Jh[yy][i],xx);
            Jh[xx].PB(Jh[yy][i]);
        }
        copy(rt[Now],oo[t],1,n);
        Jh[yy].clear();
    }
    inline void Build(int &x,int l,int r)
    {
        x=++cnt;
        if(l==r)
        {
            T[x].id=l; return;
        }
        int mid=(l+r)>>1;
        Build(T[x].ls,l,mid); Build(T[x].rs,mid+1,r);
    }
    inline void copy(int &x,int y,int l,int r)
    {
        x=y;
    }
    inline void Chag(int &x,int y,int l,int r,int Pos,int Val)
    {
        x=++cnt; T[x]=T[y];
        if(l==r)
        {
            T[x].id=Val; return;
        }
        int mid=(l+r)>>1;
        if(Pos<=mid) Chag(T[x].ls,T[y].ls,l,mid,Pos,Val);
        else Chag(T[x].rs,T[y].rs,mid+1,r,Pos,Val);
    }
    inline int Que(int x,int l,int r,int Pos)
    {
        if(l==r) return T[x].id;
        int mid=(l+r)>>1;
        if(Pos<=mid) return Que(T[x].ls,l,mid,Pos);
        else return Que(T[x].rs,mid+1,r,Pos);
    }
    int main()
    {
        freopen("history.in","r",stdin);
        freopen("history.out","w",stdout);
        int i,C=0,x,y,z,Last; char S[5];
        R(n); R(m);
        for(i=1;i<=n;i++) {fa[i]=i; sz[i]=1; Jh[i].PB(i);}
        Build(rt[Now=0],1,n);
    //    for(i=1;i<=n;i++) cout<<Que(rt[Now],1,n,i)<<' ';
    //    putchar('
    ');
        int Test=0;
        while(m--)
        {
            scanf("%s",S+1);
            switch (S[1])
            {
                case 'K':
                    R(C);
                    break;
                case 'R':
                    R(x); R(y);
                    x=(x+Last*C)%n; y=(y+Last*C)%n;
                    x++; y++;
    //                cout<<"RRR"<<' '<<x<<' '<<y<<endl;
                    Now++;
                    ubbon(x,y);
                    break;
                case 'T':
                    R(x); R(y); R(z);
                    x++; y++;
                    if(x==y) {puts("N"); Last=1; break;}
                    int xx=gf(x),yy=gf(y);
                    if(xx==yy)
                    {
                        if(Now<z) puts("Y"),Last=0;
                        else
                        {
                            int c1=Que(rt[Now-z],1,n,x),c2=Que(rt[Now-z],1,n,y);
                            if(c1==c2) puts("N"),Last=1;
                            else puts("Y"),Last=0;
                        }
                    }
                    else puts("N"),Last=1;
    //                if(++Test==185) return 0;
                    break;
            }
    //        for(i=1;i<=n;i++) cout<<Que(rt[Now],1,n,i)<<' ';
    //        putchar('
    ');
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【BZOJ1014】【JSOI2008】火星人prefix
    [agc011e]increasing numbers
    NOIp2018模拟赛四十一
    拉格朗日插值&&快速插值
    NOIp2018模拟赛四十
    (2016北京集训十四)【xsy1557】task
    (2016北京集训十四)【xsy1556】股神小D
    数据泵导入ORA-39082报错解决
    OracleDBA职责—备份与恢复技术—概念
    OracleDBA职责—备份与恢复技术—RMAN3
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/11222271.html
Copyright © 2011-2022 走看看