NOIP模擬 到不了
阿新 • • 發佈:2018-12-13
- 這道題我們首先看到lca會想到倍增,但是發現還有合併的操作
- 這就尷尬了,考場上直接打了個暴力然後愉快的報零了
- 這時我們也不慌,下來之後我們也沒想到好方法,看網上題解發現居然用LCT(我沒學)
- 當然博主不是一個想學新方法的人
- 於是開始鑽研線上操作
- 我們對於每次操作直接將原來的圖重建一次
- 然後強行再次運算倍增
- 為了避免超時當然要加上輸入輸出優化
- 下面是程式碼:
#include<bits/stdc++.h>
using namespace std;
const int Max = 1e5+5;
int fa[Max][21],d[Max],
rt[Max],root[Max] ,
size[Max],head[Max * 2],
cnt = 0;
void read(int &x)
{
int f = 1;
x = 0;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
x = x * 10 + c - '0';
c = getchar();
}
x *= f;
return;
}
void write (int x)
{
if (x < 0) putchar('-'),x = -x;
if (x > 9) write(x/10);
putchar(x % 10 + '0');
}
struct node
{
int next,to;
}e[Max * 2];
void add(int u,int v)
{
e[++cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt;
e[++cnt].next = head[v];
e[cnt].to = u;
head[v] = cnt;
}
int n,m,q,E;
void rebuild (int x,int fr)
{
for (int i = 1; i <= 20; i++)
fa[x][i] = fa[fa[x][i-1]][i-1];
for (int i = head[x]; i; i = e[i].next)
{
int to = e[i].to;
if (to == fr) continue;
d[to] = d[x] + 1;
fa[to][0] = x;
rebuild(to,x);
}
}
void dfs(int x, int fr)
{
fa[x][0] = fr;
for (int i = head[x]; i; i = e[i].next)
{
int to = e[i].to;
if (to == fr) continue;
d[to] = d[x] + 1;
dfs(to,x);
size[x] += size[to];
}
}
int find(int x)
{
for (int i = 20; i >= 0; i--)
if(fa[x][i]) x = fa[x][i];
return x;
}
int lca(int x,int y)
{
if (d[x] < d[y]) swap(x,y);
for (int i = 20; i >= 0; i--)
if(d[x] - (1 << i) >= d[y])
x = fa[x][i];
if (x == y) return x;
for (int i = 20; i >= 0; i--)
if(fa[x][i] != fa[y][i])
{
x = fa[x][i];
y = fa[y][i];
}
return fa[x][0];
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
read(n);
read(m);
for (int i = 1; i <= m; i++)
read(rt[i]);
read(E);
for (int i = 1; i <= n-m; i++)
{
int x,y;
read(x);
read(y);
add(x,y);
}
for (int i = 1; i <= n; i++)
size[i] = 1;
for (int i = 1; i <= m; i++)
{
d[rt[i]] = 1;
dfs(rt[i],0);
}
for (int i = 1; i <= 20; i++)
for (int j = 1; j <= n; j++)
fa[j][i] = fa[fa[j][i - 1]][i - 1];
for (int i = 1; i <= n; i++)
{
int o = find(i);
if (o) root[i] = o;
else root[i] = i;
}
read(q);
while (q--)
{
int op,u,v;
read(op);
read(u);
read(v);
if (op == 1)
{
int x = find(u),
y = find(v);
if (x == y) continue;
if (size[x] > size[y])
{
fa[v][0] = u;
size[x] += size[y];
d[v] = d[u] + 1;
root[y] = root[x];
add(u,v);
rebuild(v,u);
}
else
{
fa[u][0] = v;
size[y] += size[x];
d[u] = d[v] + 1;
root[y] = root[x];
add(u,v);
rebuild(u,v);
}
}
else
{
if (find(u) != find(v))
{
printf("orzorz\n");
continue;
}
int x = find(u);
int o = lca(u,v),
t = lca(root[x],v);
if (d[o] < d[t]) o = t;
t = lca(root[x],u);
if (d[o] < d[t]) o = t;
write(o);
putchar('\n');
}
}
return 0;
}