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

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

Source

Solution

  数据辣么有节奏感是什么鬼啦~

  还有带删除并查集是什么鬼啦~

  反正就是LCT搞一搞。连边就是link(x, y),删边就是cut(x, y),查询就是看find_root(x)是否等于find_root(y)。

  然后还有些splay函数access函数什么的就不用说了。

  第一道LCT的题,好像写+调试共用40分钟。。。好慢。。。

  常数大得飞起QAQ

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 struct LCT
  4 {
  5     int c[2], fa, rev;
  6     int& operator [] (int i)
  7     {
  8         return c[i];
  9     }
 10 }a[10005];
 11 int top, sta[10005];
 12
 13 void scanf(int &x)
 14 {
 15     char ch = getchar();
 16     x = 0;
 17     while(ch < ‘0‘ || ch > ‘9‘)
 18         ch = getchar();
 19     while(ch >= ‘0‘ && ch <= ‘9‘)
 20         x = x * 10 + ch - 48, ch = getchar();
 21 }
 22
 23 void push_down(int k)
 24 {
 25     if(a[k].rev)
 26     {
 27         a[a[k][0]].rev ^= 1, a[a[k][1]].rev ^= 1;
 28         swap(a[k][0], a[k][1]), a[k].rev = 0;
 29     }
 30 }
 31
 32 bool isroot(int x)
 33 {
 34     return a[a[x].fa][0] != x && a[a[x].fa][1] != x;
 35 }
 36
 37 void rotate(int x)
 38 {
 39     int y = a[x].fa, z = a[y].fa;
 40     int dy = a[y][1] == x, dz = a[z][1] == y;
 41     if(!isroot(y)) a[z][dz] = x;
 42     a[y][dy] = a[x][dy ^ 1], a[a[x][dy ^ 1]].fa = y;
 43     a[x][dy ^ 1] = y, a[y].fa = x, a[x].fa = z;
 44 }
 45
 46 void splay(int x)
 47 {
 48     sta[top = 1] = x;
 49     for(int i = x; !isroot(i); i = a[i].fa)
 50         sta[++top] = a[i].fa;
 51     while(top)
 52         push_down(sta[top--]);
 53     while(!isroot(x))
 54     {
 55         int y = a[x].fa, z = a[y].fa;
 56         if(!isroot(y))
 57             if(a[y][1] == x ^ a[z][1] == y) rotate(x);
 58             else rotate(y);
 59         rotate(x);
 60     }
 61 }
 62
 63 void access(int x)
 64 {
 65     for(int i = 0; x; x = a[x].fa)
 66         splay(x), a[x][1] = i, i = x;
 67 }
 68
 69 void make_root(int x)
 70 {
 71     access(x), splay(x), a[x].rev ^= 1;
 72 }
 73
 74 void link(int x, int y)
 75 {
 76     make_root(x), a[x].fa = y;
 77 }
 78
 79 void cut(int x, int y)
 80 {
 81     make_root(x), access(y), splay(y), a[y][0] = a[x].fa = 0;
 82 }
 83
 84 int find_root(int x)
 85 {
 86     access(x), splay(x);
 87     while(a[x][0])
 88         x = a[x][0];
 89     return x;
 90 }
 91
 92 int main()
 93 {
 94     int n, m, x, y;
 95     char op[10];
 96     scanf("%d%d", &n, &m);
 97     while(m--)
 98     {
 99         scanf("%s", op);
100         scanf(x), scanf(y);
101         if(op[0] == ‘C‘) link(x, y);
102         else if(op[0] == ‘D‘) cut(x, y);
103         else puts(find_root(x) == find_root(y) ? "Yes" : "No");
104     }
105     return 0;
106 }

时间: 2024-10-30 02:14:43

[BZOJ2049] [CodeVS1839] [SDOI2008] Cave 洞穴勘测 (LCT)的相关文章

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'){

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 ************************************************

BZOJ 2049 [Sdoi2008]Cave 洞穴勘测 LCT

题意:链接 方法: LCT 解析: 搞了一下午的LCT,这道题就当做第一道模板?题.然后大概写个理解总结什么的. 首先!splay不要写挂!不要写挂! 然后对于这道题.没有什么奇怪的操作. 只有两个操作,将两个节点连起来,将两个节点之间的连边断开. 每一次询问,询问两个节点是否连通. 听起来挺简单的,一下子就想到了并查集有没有! 然而发现并查集并不可以搞. 也许是我太弱,但是我真的不会并查集的分割. 所以还是老老实实来想LCT. LCT 顾名思义,Link Cut 是其比较有代表性的操作? 首先

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

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

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

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