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];
  8 bool isroot(int x)
  9 {
 10     return c[fa[x]][0]!=x && c[fa[x]][1]!=x;
 11 }
 12 void down(int x)
 13 {
 14     if (rev[x])
 15     {
 16         rev[x]=0;
 17         rev[c[x][0]]^=1;
 18         rev[c[x][1]]^=1;
 19         swap(c[x][0],c[x][1]);
 20     }
 21 }
 22 void rotate(int x)
 23 {
 24     int y=fa[x],z=fa[y],l,r;
 25     if (c[y][0]==x)    l=0;else l=1;r=1^l;
 26     if (!isroot(y))    if (c[z][0]==y)    c[z][0]=x;else c[z][1]=x;
 27     fa[x]=z;
 28     c[y][l]=c[x][r];fa[c[x][r]]=y;
 29     c[x][r]=y;fa[y]=x;
 30 }
 31 void splay(int x)
 32 {
 33     int y=x,z,cnt=0;
 34     while (!isroot(y))
 35     {
 36         a[++cnt]=y;
 37         y=fa[y];
 38     }
 39     a[++cnt]=y;
 40     while (cnt--)    down(a[cnt+1]);
 41     while (!isroot(x))
 42     {
 43         y=fa[x];z=fa[y];
 44         if (!isroot(y))
 45             if (c[y][0]==x ^ c[z][0]==y)
 46                 rotate(x);
 47             else rotate(y);
 48         rotate(x);
 49     }
 50 }
 51 void access(int x)
 52 {
 53     int t=0;
 54     while (x)
 55     {
 56         splay(x);
 57         c[x][1]=t;
 58         t=x;x=fa[x];
 59     }
 60 }
 61 void mt(int x)
 62 {
 63     access(x);
 64     splay(x);
 65 }
 66 void make_root(int x)
 67 {
 68     mt(x);
 69     rev[x]^=1;
 70     down(x);
 71 }
 72 void link(int x,int y)
 73 {
 74     make_root(x);
 75     fa[x]=y;
 76 }
 77 void cut(int x,int y)
 78 {
 79     make_root(x);
 80     mt(y);
 81     fa[x]=c[y][0]=0;
 82 }
 83 bool solve(int x,int y)
 84 {
 85     make_root(x);
 86     access(y);
 87     splay(x);
 88     int z=y;
 89     while (!isroot(y) && y!=fa[y])    y=fa[y];
 90     splay(z);
 91     if (x==y)    return 1;
 92     else return 0;
 93 }
 94 int main()
 95 {
 96     scanf("%d%d",&n,&Q);
 97     char str[10];
 98     while (Q--)
 99     {
100         scanf("%s%d%d",str,&x,&y);
101         if (str[0]==‘C‘)    link(x,y);
102         else    if (str[0]==‘D‘)    cut(x,y);
103         else    if (solve(x,y))    puts("Yes");else puts("No");
104     }
105     return 0;
106 }

时间: 2024-11-05 10:11:53

bzoj2049: [Sdoi2008]Cave 洞穴勘测的相关文章

【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 [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

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