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

2049: [Sdoi2008]Cave 洞穴勘测

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 10059  Solved: 4863
[Submit][Status][Discuss]

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

题解

LCT模板题,要求支持删加边及查询连通性

先说说LCT基本操作

  • ACCESS(x):把x到根的链变为重链(这条重链仅包含根到x)
  • SPLAY(x):把x转到所在的重链的splay的根
  • BEROOT(x):把x变为整棵树的树根,具体来说就是先ACCESS(x),再SPLAY(x),然后对x区间翻转(不难发现把一个点变为根后影响的是它到原根的链)
  • LINK(x,y):链接x和y,具体来说就是BEROOT(x),fa[x]=y
  • CUT(x,y):断开x和y,具体来说就是BEROOT(x),ACCESS(y),SPLAY(y),这样x必定是y的左儿子,再令fa[x]=son[y][0]=0

代码

//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define inf 1<<30
#define maxn 10005
#define eps 1e-8
using namespace std;

inline int read()
{
    int ret=0;bool fla=0;char ch=getchar();
    while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘)ch=getchar();
    if(ch==‘-‘){fla=1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){ret=ret*10+ch-‘0‘;ch=getchar();}
    return fla?-ret:ret;
}

int n,m,fa[maxn],son[maxn][2],rev[maxn],siz[maxn];

il bool pdp(int x){return son[fa[x]][1]==x;}
il bool isrt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
il void upda(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;}
il void rever(int x){rev[x]^=1;swap(son[x][0],son[x][1]);}

il void rot(int x)
{
    int f=fa[x],g=fa[f],o=pdp(x);
    if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g;
    son[f][o]=son[x][!o];fa[son[f][o]]=f;
    son[x][!o]=f;fa[f]=x;
    upda(f),upda(x);
}

il void pdn(int x)
{
    if(rev[x]){
        if(son[x][0]) rever(son[x][0]);
        if(son[x][1]) rever(son[x][1]);
        rev[x]=0;
    }
}

void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);}

il void splay(int x)
{
    pd(x);
    for(;!isrt(x);rot(x))
        if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x);
}

il void acc(int x)
{
    for(int y=0;x;y=x,x=fa[x])
        splay(x),son[x][1]=y,upda(x);
}

il void bert(int x){acc(x);splay(x);rever(x);}
il void link(int x,int y){bert(x);fa[x]=y;}
il void cut(int x,int y){bert(x);acc(y);splay(y);fa[x]=son[y][0]=0;upda(y);}

il int find(int x)
{
    acc(x);splay(x);
    while(son[x][0]) pd(x),x=son[x][0];
    return x;
}

int main()
{
    scanf("%d%d",&n,&m);
    char s[15];int x,y;
    while(m--)
    {
        scanf("%s%d%d",s,&x,&y);
        if(s[0]==‘C‘) link(x,y);
        else if(s[0]==‘D‘) cut(x,y);
        else printf("%s\n",find(x)==find(y)?"Yes":"No");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/rir1715/p/8243057.html

时间: 2024-10-09 01:37:48

【LCT】BZOJ2049 [SDOI2008]Cave 洞穴勘测的相关文章

[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: [SDOI2008]Cave 洞穴勘测 LCT

第一道LCT. 动态维护集合就好了. LCT就是一群链通过父亲关系练成一颗不太连续的树,通过儿子关系组成实边,在这里没有查找单点一说,都是直接拎起来,对于一条链他对外界的有用反馈就是他的链父亲以及需求点的真实位置,而每次cut的时候就会把标记下方好,每次spaly都会找到这个点在这条链中的真实位置,因此这个玄妙的东西就形成了. null不是一定要用只是简化了你的讨论. 千万别忘了这里的spaly的特别之处!!!!!!!! #include<cstring> #include<cstdio

bzoj2049: [Sdoi2008]Cave 洞穴勘测 lct裸题

题意:三种操作一种摧毁一条边,一种链接一条边,一种查询两个点是否联通 题解:lct的link和cut即可 /************************************************************** Problem: 2049 User: walfy Language: C++ Result: Accepted Time:1896 ms Memory:1508 kb ************************************************

bzoj2049: [Sdoi2008]Cave 洞穴勘测

[题意] 给你一个森林,要求支持动态加边删边,并会询问在某一个时刻两点是否联通. [题解] 裸的lct,模版题.第一次写对lct,没写过真的难写.... [代码] 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 using namespace std; 5 const int N=10005; 6 int n,Q,x,y; 7 int c[N][2],fa[N],rev[N],a[N]

bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门

link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isroot(int x):判断x是否为所在重链(splay)的根 void down(int x):下放各种标记 void rotate(int x):在x所在重链(splay)中将x旋转到fa[x]的位置上 void splay(int x):在x坐在重链(splay)中将x旋转到根 void acce

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)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接

【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 洞穴勘测

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

【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)以及若干通道组成,并且每条通道连接了恰好两个洞穴.假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞