洛谷P2147 [SDOI2008]Cave 洞穴勘测

题目描述

辉辉热衷于洞穴勘测。

某天,他按照地图来到了一片被标记为JSZX的洞穴群地区。经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴。假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径。 洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这条通道又会因为某种稀奇古怪的原因被毁。

辉辉有一台监测仪器可以实时将通道的每一次改变状况在辉辉手边的终端机上显示:

如果监测到洞穴u和洞穴v之间出现了一条通道,终端机上会显示一条指令 Connect u v

如果监测到洞穴u和洞穴v之间的通道被毁,终端机上会显示一条指令 Destroy u v

经过长期的艰苦卓绝的手工推算,辉辉发现一个奇怪的现象:无论通道怎么改变,任意时刻任意两个洞穴之间至多只有一条路径。

因而,辉辉坚信这是由于某种本质规律的支配导致的。因而,辉辉更加夜以继日地坚守在终端机之前,试图通过通道的改变情况来研究这条本质规律。 然而,终于有一天,辉辉在堆积成山的演算纸中崩溃了……他把终端机往地面一砸(终端机也足够坚固无法破坏),转而求助于你,说道:“你老兄把这程序写写吧”。

辉辉希望能随时通过终端机发出指令 Query u v,向监测仪询问此时洞穴u和洞穴v是否连通。现在你要为他编写程序回答每一次询问。 已知在第一条指令显示之前,JSZX洞穴群中没有任何通道存在。

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 复制

样例输入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

输出样例#1: 复制

样例输出1 cave.out
No
Yes
No

样例输出2 cave.out

Yes
No

说明

数据说明

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操作以免超时

LCT裸题

看了一下午,终于看明白点了

感觉LCT是个和玄学的东西

有空总结一下

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=2*1e6+10;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘,c=getchar();}
    return x*f;
}
struct node
{
    int ch[2],fa;
    bool rev,IsRoot;
    node(){ch[0]=ch[1]=fa=rev=0;IsRoot=1;}
}T[MAXN];
int get(int x)
{
    if(T[ T[x].fa ].ch[1]==x) return 1;
    if(T[ T[x].fa ].ch[0]==x) return 0;
    return -1;
}
void PushReverse(int x)
{
    if(!T[x].rev) return ;
    T[x].rev=0;
    swap(T[x].ch[0],T[x].ch[1]);
    T[T[x].ch[0]].rev^=1;
    T[T[x].ch[1]].rev^=1;
}
void push(int x)
{
    if(get(x)!=-1) push(T[x].fa);
    PushReverse(x);
}
int connect(int x,int fa,int how)
{
    T[x].fa=fa;
    T[fa].ch[how]=x;
}
void rotate(int x)
{
    int Y=T[x].fa;
    int R=T[Y].fa;
    int Yson=get(x);
    int Rson=get(Y);
    int B=T[x].ch[Yson^1];
    T[x].fa=R;
    if(get(Y)!=-1)
    connect(x,R,Rson);
    connect(B,Y,Yson);
    connect(Y,x,Yson^1);
}
void splay(int x)
{
    push(x);
    for(int f=T[x].fa;get(x)!=-1;rotate(x),f=T[x].fa)
        if(get(f)!=-1)
            rotate( get(f)==get(x)?f:x );
}
void access(int x)
{
    for(int t=0;x;x=T[t=x].fa)
        splay(x),T[x].ch[1]=t;
}
void MakeRoot(int x)
{
    access(x);
    splay(x);
    T[x].rev=1;
}
int link(int x,int y)
{
    MakeRoot(x);
    T[x].fa=y;
}
int cut(int x,int y)
{
    MakeRoot(x);
    access(y);
    splay(y);
    T[x].fa=T[y].ch[0]=0;
}
int find(int x)
{
    while(get(x)!=-1) x=T[x].fa;
    return x;
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    #else
    #endif
    int N=read(),M=read();
    while(M--)
    {
        char opt[10];int x,y;
        scanf("%s",opt);x=read(),y=read();
        if(opt[0]==‘Q‘)
            find(x)==find(y)?printf("Yes\n"):printf("No\n");
        else if(opt[0]==‘C‘)
            link(x,y);
        else if(opt[0]==‘D‘)
            cut(x,y);
    }
    return 0;
}
时间: 2024-10-05 23:25:37

洛谷P2147 [SDOI2008]Cave 洞穴勘测的相关文章

洛谷 2147 SDOI2008 Cave 洞穴勘测

[题解] 动态树模板题,只要求维护森林的连通性,直接上板子即可. 1 #include<cstdio> 2 #include<algorithm> 3 #define N 500010 4 #define ls (c[u][0]) 5 #define rs (c[u][1]) 6 using namespace std; 7 int n,m; 8 inline int read(){ 9 int k=0,f=1; char c=getchar(); 10 while(c<'0

BZOJ 2049([Sdoi2008]Cave 洞穴勘测-LCT)[Template:LCT]

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 4809  Solved: 2141 [Submit][Status][Discuss] Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接

BZOJ 题目2049: [Sdoi2008]Cave 洞穴勘测(link cut tree)

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 4698  Solved: 2107 [Submit][Status][Discuss] Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接

BZOJ 2049: [Sdoi2008]Cave 洞穴勘测

二次联通门 : BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 其实指针也不是很慢 我的指针代码能吊打70%的数组 及80%的指针.... /* BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 LCT 连边 删边 查询是否在同一树中时, 只需要一直向上跳 看看树根是否相同就好了 */ #include <cstdio> #include <cstdlib> #include <iostream> #define Max 400009 int

【bzoj2049】[Sdoi2008]Cave 洞穴勘测 link-cut-tree

2016-05-30  11:04:51 学习了link-cut-tree 二中神犇封禹的讲义感觉讲的超级清晰易懂啊(没有的可以q窝 算是模板吧 #include<bits/stdc++.h> #define N 10005 #define inf 1000000000 #define ll long long using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){

【BZOJ 2049】 [Sdoi2008]Cave 洞穴勘测

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 3215  Solved: 1449 [Submit][Status] Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞

【LCT】BZOJ2049 [SDOI2008]Cave 洞穴勘测

2049: [Sdoi2008]Cave 洞穴勘测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 10059  Solved: 4863[Submit][Status][Discuss] Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起

[bzoj2049][Sdoi2008]Cave 洞穴勘测_LCT

Cave 洞穴勘测 bzoj-2049 Sdoi-2008 题目大意:维护一个数据结构,支持森林中加边,删边,求两点连通性.n个点,m个操作. 注释:$1\le n\le 10^4$,$1\le m\le 2\cdot 10^5$. 想法:刚学了一发LCT,写一道照学长抄一道板子题.话说什么是LCT? 就是一个贼nb的数据结构,支持加边删边后的什么路径和子树信息啥的,这就是LCT. 艾欧欸软可以的blog 这道题,我们只需要其中的link,cut和find即可. 最后,附上代码.. ... #i

[BZOJ2049] [CodeVS1839] [SDOI2008] Cave 洞穴勘测 (LCT)

Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径.洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通