2020牛客多校八 Discovery of Cycles

http://acm.hdu.edu.cn/showproblem.php?pid=6858
思路:尺取左右端,用LCT维护连通性。

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;

int T,n,m,q;
int x[maxn],y[maxn],ans[maxn];

struct Node *null;
struct Node{
    Node *fa,*ch[2];
    int val,sum,c;
    bool reversed;
    Node(){}
    Node(int val):fa(null),val(val),sum(val),reversed(false){ch[0]=ch[1]=null;}
    void maintain(){if(this!=null)this->sum=ch[0]->sum+ch[1]->sum+val;}
    void reverse(){if(this!=null){reversed^=1;swap(ch[0],ch[1]);c=c==-1?-1:1-c;}}
    void pushdown(){if(reversed){reversed=0;ch[0]->reverse();ch[1]->reverse();}}
}pool[maxn];

void rotate(Node *&o, int d)
{
    Node *k=o->ch[d^1];
    k->ch[d]->fa=o;k->fa=o->fa;o->fa=k;
    o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->maintain();k->maintain();
    o=k;
}

void _splay(Node *&o)
{
    o->pushdown();
    if(o->c!=-1)
    {
        Node *k=o->ch[o->c];
        k->pushdown();
        if(k->c!=-1)
        {
            _splay(k->ch[k->c]);
            if(o->c==k->c)rotate(o,o->c^1);
            else rotate(o->ch[o->c],o->c);
        }
        rotate(o,o->c^1);
    }
}

bool isRoot(Node *o){return o->fa==null||(o->fa->ch[0]!=o&&o->fa->ch[1]!=o);}

void splay(Node *o)
{
    o->c=-1;
    while(!isRoot(o))
    {
        if(o==o->fa->ch[0])o->fa->c=0;
        else o->fa->c=1;
        o=o->fa;
    }
    _splay(o);
}

Node *access(Node *o)
{
    Node *k=null;
    while(o!=null)
    {
        splay(o);
        o->ch[1]=k;
        o->maintain();
        k=o;
        o=o->fa;
    }
    while(k->ch[0]!=null)k=k->ch[0];
    return k;
}

void makeRoot(Node *x)
{
    access(x);
    splay(x);
    x->reverse();
}

void link(int x,int y)
{
    makeRoot(pool+x);
    (pool+x)->fa=pool+y;
}

bool connected(int x,int y)
{
    return access(pool+x)==access(pool+y);
}

int Distance(int x,int y)
{
    makeRoot(pool+x);
    access(pool+y);
    splay(pool+y);
    return (pool+y)->sum;
}

void cut(int x,int y)
{
    makeRoot(pool+x);
    access(pool+y);
    splay(pool+x);
    (pool+x)->ch[1]->fa=null;
    (pool+x)->ch[1]=null;
    (pool+x)->maintain();
}

int main()
{
   // freopen("input.in","r",stdin);
    null=new Node();
    cin>>T;
    while(T--)
    {
        cin>>n>>m>>q;
        for(int i=1;i<=n;i++)pool[i].fa=pool[i].ch[0]=pool[i].ch[1]=null,pool[i].reversed=false;
        for(int i=1;i<=m;i++)scanf("%d%d",&x[i],&y[i]);
        int l=1,r=1;
        while(l<=m)
        {
            if(r>m){ans[l]=1e9;l++;continue;}
            while(!connected(x[r],y[r]))
            {
                               
                link(x[r],y[r]);
                ++r;
                if(r>m)break;
            }
            if(r>m){ans[l]=1e9;l++;continue;}
            ans[l]=r;
            cut(x[l],y[l]);
            l++;
        }
        int last=0;
        int _l,_r,k1,k2;
        while(q--)
        {
            scanf("%d%d",&_l,&_r);
            k1=(_l^last)%m+1,k2=(_r^last)%m+1;
            l=min(k1,k2),r=max(k1,k2);
            if(ans[l]<=r)last=1;
            else last=0;
            puts(last?"Yes":"No");
        }
    }
    //for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值