[bzoj2049][LCT]洞穴探测cave

109 篇文章 4 订阅
10 篇文章 0 订阅

Description

辉辉热衷于洞穴勘测。某天,他按照地图来到了一片被标记为JSZX的洞穴群地区。经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴。假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径。洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这条通道又会因为某种稀奇古怪的原因被毁。辉辉有一台监测仪器可以实时将通道的每一次改变状况在辉辉手边的终端机上显示:如果监测到洞穴u和洞穴v之间出现了一条通道,终端机上会显示一条指令
Connect u v 如果监测到洞穴u和洞穴v之间的通道被毁,终端机上会显示一条指令 Destroy u v
经过长期的艰苦卓绝的手工推算,辉辉发现一个奇怪的现象:无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径。因而,辉辉坚信这是由于某种本质规律的支配导致的。因而,辉辉更加夜以继日地坚守在终端机之前,试图通过通道的改变情况来研究这条本质规律。然而,终于有一天,辉辉在堆积成山的演算纸中崩溃了……他把终端机往地面一砸(终端机也足够坚固无法破坏),转而求助于你,说道:“你老兄把这程序写写吧”。辉辉希望能随时通过终端机发出指令
Query u
v,向监测仪询问此时洞穴u和洞穴v是否连通。现在你要为他编写程序回答每一次询问。已知在第一条指令显示之前,JSZX洞穴群中没有任何通道存在。

Input

第一行为两个正整数n和m,分别表示洞穴的个数和终端机上出现过的指令的个数。以下m行,依次表示终端机上出现的各条指令。每行开头是一个表示指令种类的字符串s(”Connect”、”Destroy”或者”Query”,区分大小写),之后有两个整数u和v
(1≤u, v≤n且u≠v) 分别表示两个洞穴的编号。

Output

对每个Query指令,输出洞穴u和洞穴v是否互相连通:是输出”Yes”,否则输出”No”。(不含双引号)

Sample Input

样例输入1 cave.in

200 5

Query 123 127

Connect 123 127

Query 123 127

Destroy 127 123

Query 123 127

样例输入2 cave.in

3 5

Connect 1 2

Connect 3 1

Query 2 3

Destroy 1 3

Query 2 3

Sample Output

样例输出1 cave.out

No

Yes

No

样例输出2 cave.out

Yes

No

HINT

数据说明 10%的数据满足n≤1000, m≤20000 20%的数据满足n≤2000, m≤40000 30%的数据满足n≤3000,
m≤60000 40%的数据满足n≤4000, m≤80000 50%的数据满足n≤5000, m≤100000
60%的数据满足n≤6000, m≤120000 70%的数据满足n≤7000, m≤140000 80%的数据满足n≤8000,
m≤160000 90%的数据满足n≤9000, m≤180000 100%的数据满足n≤10000, m≤200000
保证所有Destroy指令将摧毁的是一条存在的通道本题输入、输出规模比较大,建议c\c++选手使用scanf和printf进行I\O操作以免超时

打一发call

首先欢迎大家前往我们做的小白菜oj看题意

题解

重学LCT,学懂了之后又发现这是一个智障的算法= =
大体思路就是:对于一棵树,我们使用多棵伸展树维护这棵树的结构
首先对整棵树建伸展树,那么在splay的过程里,会有各种限制条件将一大棵伸展树分成一小棵一小棵伸展树
伸展树中,根的左边是在原树中层数比根小的,右边是层数比根大的
这里推一下Chan老师的blog
然后access(x)这个函数的精髓就是将root~x这条路径变为一棵伸展树,也就是将限制条件改一改然后就重新变成另一些伸展树了
对于Mark_root(x),先将root~x变为伸展树也就是access(x),然后x旋转到根。但是旋转的过程中root会转到x的左子树,那么层数还是比x小也就是根还没有改变。所以需要反转x的左右子树
至于剩下的。。代码见吧
就是裸题来的

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct trnode
{
    int f,son[2];
    bool fz;
    trnode(){fz=false;}
}tr[11000];
void reverse(int x)
{
    tr[x].fz=false;
    swap(tr[x].son[0],tr[x].son[1]);
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[lc].fz^=1;
    tr[rc].fz^=1;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int R,r;

    R=f;r=tr[x].son[w];
    tr[R].son[1-w]=r;
    if(r!=0)tr[r].f=R;

    R=ff;r=x;
    tr[r].f=R;
    if(tr[R].son[0]==f)tr[R].son[0]=r;
    else if(tr[R].son[1]==f)tr[R].son[1]=r;

    R=x;r=f;
    tr[R].son[w]=r;
    tr[r].f=R;  
}
int tmp[11000];
void splay(int x,int rt)
{
    int s=0,i=x;
    while(tr[i].f!=0 && (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!=0)
    {
        i=tmp[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(tr[f].son[0]==x)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[0]==f && tr[f].son[1]==x){rotate(x,0);rotate(x,1);}
            else if(tr[ff].son[1]==f && tr[f].son[1]==x){rotate(f,0);rotate(x,0);}
            else {rotate(x,1);rotate(x,0);}
        }
    }
}
void access(int x)
{
    int y=0;
    while(x!=0)
    {
        splay(x,0);
        tr[x].son[1]=y;
        if(y!=0)tr[y].f=x;
        y=x;x=tr[x].f;
    }
}
void mark_root(int x)
{
    access(x);
    splay(x,0);
    tr[x].fz^=1;
}
void link(int x,int y)
{
    mark_root(x);tr[x].f=y;access(x);
}
void cut(int x,int y)
{
    mark_root(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;
}
int main()
{
    char ss[10];
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    while(m--)
    {
        scanf("%s%d%d",ss+1,&x,&y);
        if(ss[1]=='C')link(x,y);
        else if(ss[1]=='D')cut(x,y);
        else
        {
            if(find_root(x)==find_root(y))printf("Yes\n");
            else printf("No\n");
        }
    }
    return 0;
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值