spoj DYNALCA - Dynamic LCA

http://www.spoj.com/problems/DYNALCA/

此题link、cut要求不能换根,当然也保证link时其中一个点必定已经是根。

方法:

void link(Node *x,Node *y)
{
    access(x);splay(x);
    x->fa=y;
}
void cut(Node *x)
{
    access(x);splay(x);
    x->ch[0]->fa=NULL;x->ch[0]=NULL;
}

曾经的错误思路:

void cut(Node *x)
{
    access(x->fa);x->fa=NULL;
}

因为此时x->fa不一定是splay维护的序列上x的前一个元素(只是splay上x的父亲罢了,在实际序列中它们的关系可以任意)

求lca?x,y的lca就是先access(x)后,在access(y)的过程中,“最后一次虚边变成实边的位置”。实际也就是access(y)的过程中最后一次的lst

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 namespace LCT
  5 {
  6 struct Node
  7 {
  8     Node *ch[2],*fa;
  9     bool rev;
 10     int num;
 11     void upd()    {}
 12     void pd()
 13     {
 14         if(rev)
 15         {
 16             swap(ch[0],ch[1]);
 17             if(ch[0])    ch[0]->rev^=1;
 18             if(ch[1])    ch[1]->rev^=1;
 19             rev=0;
 20         }
 21     }
 22 }nodes[100100];
 23 int mem;
 24 Node *getnode()
 25 {
 26     return nodes+(mem++);
 27 }
 28 bool isroot(Node *x)
 29 {
 30     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
 31 }
 32 bool gson(Node *o)    {return o==o->fa->ch[1];}
 33 void rotate(Node *o,bool d)
 34 {
 35     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;
 36     o->ch[!d]=k->ch[d];k->ch[d]=o;
 37     o->upd();k->upd();
 38     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
 39 }
 40 Node *st[300100];int top;
 41 void solvetag(Node *o)
 42 {
 43     while(!isroot(o))    st[++top]=o,o=o->fa;
 44     st[++top]=o;
 45     while(top)    st[top--]->pd();
 46 }
 47 void splay(Node *o)
 48 {
 49     solvetag(o);
 50     Node *fa,*fafa;bool d1,d2;
 51     while(!isroot(o))
 52     {
 53         fa=o->fa;d1=(o==fa->ch[0]);
 54         if(isroot(fa))    rotate(fa,d1);
 55         else
 56         {
 57             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);
 58             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);
 59             else    rotate(fa,d1),rotate(fafa,d2);
 60         }
 61     }
 62 }
 63 void access(Node *o)
 64 {
 65     for(Node *lst=NULL;o;lst=o,o=o->fa)
 66     {
 67         splay(o);
 68         o->ch[1]=lst;o->upd();
 69     }
 70 }
 71 Node *gtop(Node *o)
 72 {
 73     access(o);splay(o);
 74     for(;o->ch[0];o=o->ch[0],o->pd());
 75     splay(o);return o;
 76 }
 77 void mtop(Node *o)    {access(o);splay(o);o->rev^=1;}
 78 void link(Node *x,Node *y)
 79 {
 80     access(x);splay(x);
 81     x->fa=y;
 82 }
 83 //void splay(Node *o,Node *rt)
 84 //{
 85 //    if(isroot(rt))    splay(o);
 86 //    bool d=gson(rt);Node *t=rt->fa;
 87 //    t->ch[d]=NULL;rt->fa=NULL;
 88 //    splay(o);
 89 //    t->ch[d]=o;o->fa=t;
 90 //}
 91 void cut(Node *x)
 92 {
 93     access(x);splay(x);
 94     x->ch[0]->fa=NULL;x->ch[0]=NULL;
 95 }
 96 Node *lca(Node *x,Node *y)
 97 {
 98     access(x);Node *lst=NULL;
 99     for(;y;lst=y,y=y->fa)
100     {
101         splay(y);
102         y->ch[1]=lst;y->upd();
103     }
104     return lst;
105 }
106 }
107 LCT::Node *nd[300100];
108 int n,q;char tmp[20];
109 int main()
110 {
111     int i,x,y;
112     scanf("%d%d",&n,&q);
113     for(i=1;i<=n;i++)
114     {
115         nd[i]=LCT::getnode();
116         nd[i]->num=i;
117     }
118     while(q--)
119     {
120         scanf("%s",tmp);
121         switch(tmp[1])
122         {
123         case ‘i‘:
124             scanf("%d%d",&x,&y);
125             LCT::link(nd[x],nd[y]);
126             break;
127         case ‘u‘:
128             scanf("%d",&x);
129             LCT::cut(nd[x]);
130             break;
131         case ‘c‘:
132             scanf("%d%d",&x,&y);
133             printf("%d\n",LCT::lca(nd[x],nd[y])->num);
134             break;
135         }
136     }
137     return 0;
138 }

原文地址:https://www.cnblogs.com/hehe54321/p/8969671.html

时间: 2024-10-15 05:07:02

spoj DYNALCA - Dynamic LCA的相关文章

【题解】Luogu SP8791 DYNALCA - Dynamic LCA

原题传送门 这题用Link-Cut-Tree解决,Link-Cut-Tree详解 这道题的难点就在如何求LCA: 我们珂以先对其中一个点进行access操作,然后对另一个点进行access操作,因为LCA到根的边一定都由第一次access变为实边了,在之后的这一次access操作的最后一条从虚边变为实边的边的父亲就是两点的LCA 回求LCA后,剩下的几乎是模板,但有两种做法 1.建立虚拟点n+1,保证一直是一颗有n+1个点的树,写起来比较无脑(lct部分珂以复制),常数比较大 #include

Count on a tree SPOJ 主席树+LCA(树链剖分实现)(两种存图方式)

Count on a tree SPOJ 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)[GO!] 题意 是说有棵树,每个节点上都有一个值,然后让你求从一个节点到另一个节点的最短路上第k小的值是多少. 解题思路 看到这个题一想以为是树链剖分+主席树,后来写着写着发现不对,因为树链剖分我们分成了一小段一小段,这些小段不能合并起来求第k小,所以这个想法不对.奈何不会做,查了查题解,需要用LCA(最近公共祖先),然后根据主席树具有区间加减的性质,我们

BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

2588: Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数表示点i的权值. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边. 最后M行每行两个整数(u,v,k),表示一组询问.

bzoj 2588: Spoj 10628. Count on a tree LCA+主席树

2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数

【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA

[BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数表示点i的权值. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边. 最后M行每行两个整数(u,v,k),表示一组

SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight. We will ask you to perform the following operation: u v k : ask for the kth minimum weight on the path from node u 

spoj COT - Count on a tree (树上第K小 LCA+主席树)

链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们可以用dfs跑出所有点离根的距离-dep[i](根为1,dep[1]也为1)在dfs的过程 中,我们对每一个节点建一棵线段树,那么[a,b]就是:root[a] + root[b] - root[lca(a,b)] - root[f[lca(a,b)]]; (因为a-b的路径上的权值还要算上lca(

【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)

You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some instructions of the following form: D

【LCA】SPOJ QTREE2

You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some instructions of the following form: D