[SDOI2008]洞穴勘测

  

题目描述

辉辉热衷于洞穴勘测。

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

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

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

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

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

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

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

 

lct模板题。

lct:树链与splay的结合。用splay维护数列,相当于按深度为关键字。

主要操作:

access:打通x到整棵树的树根。

move_to_root:将x移动到根。

和splay思想差不多。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 10500
#define M 200050
int n,m;
struct balan
{
    int ch[2],fa;
    bool res,rt;
}tr[N];
void reserve(int x)
{
    tr[x].res^=1;
    swap(tr[x].ch[0],tr[x].ch[1]);
}
void pushdown(int x)
{
    if(tr[x].res)
    {
        tr[x].res = 0;
        reserve(tr[x].ch[0]);
        reserve(tr[x].ch[1]);
    }
}
void down(int x)
{
    if(!tr[x].rt)down(tr[x].fa);
    pushdown(x);
}
void rotate(int x)
{
    int y = tr[x].fa,z =tr[y].fa,k = (tr[y].ch[1]==x);
    if(tr[y].rt)tr[x].rt = 1,tr[y].rt = 0;
    else tr[z].ch[tr[z].ch[1]==y]=x;
    tr[x].fa = z;
    tr[tr[x].ch[!k]].fa = y,tr[y].ch[k] = tr[x].ch[!k];
    tr[x].ch[!k] = y,tr[y].fa = x;
}
void splay(int x)
{
    down(x);
    while(!tr[x].rt)
    {
        int y = tr[x].fa,z  = tr[y].fa;
        if(!tr[y].rt)
            ((tr[y].ch[1]==x)^(tr[z].ch[1]==y))?rotate(x):rotate(y);
        rotate(x);
    }
}
void access(int x)
{
    int y = 0;
    while(x)
    {
        splay(x);
        tr[tr[x].ch[1]].rt=1;tr[y].rt=0;
        tr[x].ch[1] = y;
        y = x,x = tr[x].fa;
    }
}
void mtr(int x)
{
    access(x);
    splay(x);
    reserve(x);
}
void link(int x,int y)
{
    mtr(x);
    tr[x].fa = y;
}
void cut(int x,int y)
{
    mtr(x);
    access(y);
    splay(y);
    tr[y].ch[0] = tr[x].fa = 0;
    tr[x].rt = 1;
}
bool query(int x,int y)
{
    mtr(x);
    access(y);
    splay(x);//!!!!!
    while(!tr[y].rt)y=tr[y].fa;
    return (x==y);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)tr[i].rt = 1;
    char ch[15];
    for(int u,v,i=1;i<=m;i++)
    {
        scanf("%s%d%d",ch,&u,&v);
        if(ch[0]=='Q')
        {
            printf(query(u,v)?"Yes\n":"No\n");
        }else if(ch[0]=='C')
        {
            link(u,v);
        }else
        {
            cut(u,v);
        }
    }
    return 0;
}

 

posted @ 2018-09-12 17:26  LiGuanlin  阅读(98)  评论(0编辑  收藏  举报