1. 程式人生 > >NOIP模擬 到不了

NOIP模擬 到不了

在這裡插入圖片描述 在這裡插入圖片描述

  • 這道題我們首先看到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; }