您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: