HDU-5967 小R与手机(LCT)
2017-08-09 09:59
323 查看
小R与手机
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 456 Accepted Submission(s): 108
Problem Description
小R有n部手机,为了便于管理,他对一些手机设置了“呼叫转移”的功能。
具体来说,第i ( 1 <= i <= n )部手机有个参数 ai(0<=ai<=n,ai≠ i
)。若 ai ≠ 0
则表示第i部手机接到电话时会将电话无条件转移给第 ai部手机(此时如果 aai≠0,
会继续进行呼叫转移)。
如果一部手机接到电话会导致至少 109次呼叫转移,则这次电话无法接通。
现在有m个事件依次发生,具体如下:
∙1
x y表示将第x部手机的参数设置为y,即将 ax设置为y
;
∙2
x表示询问给第x部手机打电话,最终接到电话的手机编号(如果无法接通, 则编号为-1 )。
小R当然知道怎么做啦!但是他想考考你。
Input
只包含一组测试数据。
输入的第一行有两个整数n, m。保证1 <= n, m <= 2 * 105。
接下来一行,包含n个整数,第i个整数为 ai。
接下来m行,每一行为一个事件,具体格式见问题描述。
对于事件1,保证1 <= x <= n, 0 <= y <= n, x ≠ y
;对于事件2,保证1 <= x <= n
Output
对每个询问事件输出一行一个整数,表示最终接到电话的手机编号,如果无法接 通,输出-1。
Sample Input
5 6
2 3 4 5 0
2 2
2 5
1 4 3
2 1
1 4 0
2 1
Sample Output
5
5
-1
4
LCT,如果某次加边时会构成环,那么这条边的两端一定是根节点和其子树节点,每次加边的时候判断一下是否会构成环,会的话就保存好那条边,还要判断本来是否有环,有环的话要把环拆开并把保存好的边加入Splay-tree中
#include<bits/stdc++.h>
#define rson m+1,r,rt<<1|1
#define lson l,m,rt<<1
#define FIN freopen("input.txt","r",stdin);
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int MX = 2e5 + 5;
typedef pair<int, int> PII;
int n, m, a[MX];
int ch[MX][2], pre[MX], clr[MX];
bool root[MX];
void init() {
for (int i = 0; i <= n; i++) {
ch[i][0] = ch[i][1] = clr[i] = 0;
pre[i] = 0;
root[i] = 1;
}
}
void Rotate(int x) {
int y = pre[x], kind = ch[y][1] == x;
ch[y][kind] = ch[x][!kind];
pre[ch[y][kind]] = y;
pre[x] = pre[y];
pre[y] = x;
ch[x][!kind] = y;
if (root[y]) root[y] = 0, root[x] = 1;
else ch[pre[x]][ch[pre[x]][1] == y] = x;
}
int t;
void Splay(int x) {
while (!root[x]) {
int f = pre[x], ff = pre[f];
if (!root[f]) {
if ((ch[ff][1] == f) == (ch[f][1] == x)) Rotate(f);
else Rotate(x);
}
Rotate(x);
}
}
int Access(int x) {
int y = 0;
t = x;
while (x) {
Splay(x);
root[ch[x][1]] = 1; //在辅助树中切除右子树(曾经的偏爱子节点)
root[ch[x][1] = y] = 0;
x = pre[y = x];
}
return y;
}
int findroot(int x) {
Access(x);
Splay(x);
while (ch[x][0]) x = ch[x][0];
Splay(x);
return x;
}
void cut(int v) {
Access(v);
Splay(v);
pre[ch[v][0]] = pre[v];
pre[v] = 0;
root[ch[v][0]] = 1;
ch[v][0] = 0;
}
void link(int u, int v) {
Access(v);
Splay(v);
pre[v] = u;
}
void Link(int u, int v) {
int rt = findroot(v);
if (rt == v) clr[rt] = 0;
else cut(v);
if (clr[rt] && findroot(clr[rt]) != rt) {
link(clr[rt], rt);
clr[rt] = 0;
}
if(u==0) return;
if (findroot(u) == v) clr[v] = u;
else link(u, v);
}
int main() {
//freopen("in.txt", "r", stdin);
while (~scanf("%d%d", &n, &m)) {
init();
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) if (a[i]) Link(a[i], i);
for (int i = 1; i <= m; i++) {
int op, x, y;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &x, &y);
Link(y, x);
} else {
scanf("%d", &x);
x = findroot(x);
printf("%d\n", clr[x] ? -1 : x);
}
}
}
return 0;
}
相关文章推荐
- hdu 5967 小R与手机(LCT裸题)
- HDU 5967 小R与手机 (LCT)
- Hdu 5967 小R与手机
- HDU 5967 小R与手机(Link Cut Tree 基环树森林)
- HDU 5967 小R与手机(动态树)
- HDU 5967 小R与手机 CDQ分治+回滚并查集
- 动态树(LCT):HDU 4010 Query on The Trees
- hdu 4010 Query on The Trees (lct模板)
- Hdu 5052 Yaoge’s maximum profit 动态树 LCT link-cut tree
- [LCT 树状数组] HDU 5333 Undirected Graph
- Hdu 4718 The LCIS on the Tree 动态树 LCT
- HDU 2081 手机短号
- hdu 4010 Lct动态链接树
- HDU 2081 手机短号
- hdu 2526 浪漫手机
- hdu 5002 (LCT模板)
- hdu 2081 手机短号
- HDU 5458(Stability-LCT维护连通图2点间割边个数)
- HDU 4718 The LCIS on the Tree (动态树LCT)
- hdu 5333 Undirected Graph (LCT)