1. 程式人生 > >CodeForces 1084 F Max Mex

CodeForces 1084 F Max Mex

Max Mex

題意:問在樹上的所有路中mex值最大是多少。

題解:

用線段樹維護值。

區間[L,R]意味著 區間[L,R]的數可不可以合併。

重點就是合併的問題了。

首先合法的區間只有3種:

1. 一個點。

2. 一條從上到下的線段  即 u->v  u = lca(u,v)。

3.一條從下到上到下的線段 u -> p -> v  p = lca(u,v) 

 1 和 1 可以直接合並, 合併之後可能成為 2 或者成為3。

 1 和 2 合併的時候 可能變成 2 或者 3。 注意的是 1 往上爬的時候可能出現在 2 的中間位置而不是端點位置。

 1 和 3 合併的之後 只會變成 3。並且 p 是不會變得,只有 u 和 v 會變。

 2 和 2 合併的時候 可能保持2 也可以變成3。

 2 和 3 合併的時候 只會保持3, 並且 p 一樣不會邊,只有u 和 v 會變。  1 3 合併的操作 和 2 3 合併的操作是一樣的。

 3 和 3 合併的時候 只會保持3, 還是p不會邊, u 和 v 會變。

所以 根據前面說的 我們要記錄的是 type, u, v, p,ok。

 

詢問的時候,我們先問出[1,x]哪一段是合法的,然後再在右邊去詢問能不能把右邊的併到[1,x]上。

 

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define
lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) typedef pair<int,int> pll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL _INF = 0xc0c0c0c0c0c0c0c0; const LL mod = (int)1e9+7; const int N = 2e5 + 100; int anc[N][20]; int v[N], deep[N]; vector<int> vc[N]; void dfs(int o){ for(int x : vc[o]){ deep[x] = deep[o]+1; anc[x][0] = o; for(int i = 1; i < 19; ++i) anc[x][i] = anc[anc[x][i-1]][i-1]; dfs(x); } } int lca(int u, int v){ if(deep[u] > deep[v]) swap(u,v); int k = deep[v] - deep[u]; for(int i = 19; i >= 0; --i){ if((k>>i)&1) v = anc[v][i]; } if(u == v) return u; for(int i = 19; i >= 0; --i){ if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i]; } return anc[u][0]; } int ok[N<<2], pre[N<<2], type[N<<2], low[N<<2][2]; void Merge(int rt, int ls, int rs){ ok[rt] = 0; if(!ok[ls] || !ok[rs]) return; if(pre[ls] == low[ls][0] && pre[rs] == low[rs][0]){ int fp = lca(pre[ls], pre[rs]); ok[rt] = 1; pre[rt] = fp; if(fp == pre[ls] || fp == pre[rs]){ type[rt] = 1; if(fp == low[ls][0]) low[rt][0] = low[rs][0]; else low[rt][0] = low[ls][0]; } else { type[rt] = 2; low[rt][0] = pre[ls]; low[rt][1] = pre[rs]; } return ; } if(pre[ls] == low[ls][0]) swap(ls, rs); if(type[ls] == 1 && type[rs] == 1 && pre[rs] == low[rs][0]){ int fp = lca(pre[ls], pre[rs]); int sp = lca(low[ls][0], low[rs][0]); pre[rt] = fp; if(fp == sp){ if(fp == pre[rs]) { ok[rt] = 1; type[rt] = 1; low[rt][0] = low[ls][0]; } else { ok[rt] = 1; type[rt] = 2; low[rt][0] = low[ls][0]; low[rt][1] = low[rs][0]; } } else if((fp == pre[ls] || fp == pre[rs]) && (sp == low[ls][0]||sp == low[rs][0])){ ok[rt] = 1; type[rt] = 1; if(sp == low[ls][0]) low[rt][0] = low[rs][0]; else low[rt][0] = low[ls][0]; } return ; } if(type[ls] == 1 && type[rs] == 1){ int fp = lca(pre[ls], pre[rs]); int sp = lca(low[ls][0], low[rs][0]); pre[rt] = fp; if(fp == sp){ type[rt] = 2; ok[rt] = 1; low[rt][0] = low[ls][0]; low[rt][1] = low[rs][0]; } else if((fp == pre[ls] || fp == pre[rs]) && (sp == low[ls][0]||sp == low[rs][0])){ ok[rt] = 1; type[rt] =1 ; if(sp == low[ls][0]) low[rt][0] = low[rs][0]; else low[rt][0] = low[ls][0]; } else ok[rt] = 0; return ; } if(type[ls] + type[rs] == 3){ if(type[ls] == 2) swap(ls, rs); int fp = lca(pre[ls], pre[rs]); if(fp != pre[rs]) ok[rt] = 0; else { type[rt] = 2; pre[rt] = fp; int sp = lca(low[ls][0], low[rs][0]); if(sp == low[ls][0]){ low[rt][0] = low[rs][0]; low[rt][1] = low[rs][1]; ok[rt] = 1; return ; } if(sp == low[rs][0]){ low[rt][0] = low[ls][0]; low[rt][1] = low[rs][1]; ok[rt] = 1; return ; } sp = lca(low[ls][0], low[rs][1]); if(sp == low[ls][0]){ low[rt][0] = low[rs][0]; low[rt][1] = low[rs][1]; ok[rt] = 1; return ; } if(sp == low[rs][1]){ low[rt][0] = low[rs][0]; low[rt][1] = low[ls][0]; ok[rt] = 1; return ; } return ; } return ; } if(type[ls] + type[rs] == 4){ type[rt] = 2; if(pre[ls] == pre[rs]){ pre[rt] = pre[ls]; int sp1 = lca(low[ls][0], low[rs][0]), sp2 = lca(low[ls][1], low[rs][1]); if((sp1 == low[ls][0] || sp1 == low[rs][0]) && (sp2 == low[ls][1] || sp2 == low[rs][1])){ ok[rt] = 1; if(sp1 == low[ls][0]) low[rt][0] = low[rs][0]; else low[rt][0] = low[ls][0]; if(sp2 == low[ls][1]) low[rt][1] = low[rs][1]; else low[rt][1] = low[ls][1]; return ; } sp1 = lca(low[ls][0], low[rs][1]), sp2 = lca(low[ls][1], low[rs][0]); if((sp1 == low[ls][0] || sp1 == low[rs][1]) && (sp2 == low[ls][1] || sp2 == low[rs][0])){ ok[rt] = 1; if(sp1 == low[ls][0]) low[rt][0] = low[rs][1]; else low[rt][0] = low[ls][0]; if(sp2 == low[ls][1]) low[rt][1] = low[rs][0]; else low[rt][1] = low[ls][1]; return ; } } } } void Update(int L, int k, int l, int r, int rt){ if(l == r){ type[rt] = ok[rt] = 1; low[rt][0] = pre[rt] = k; return ; } int m = l+r >> 1; if(L <= m) Update(L, k, lson); else Update(L, k, rson); Merge(rt, rt<<1, rt<<1|1); } void Copy(int aim, int f){ ok[aim] = ok[f]; pre[aim] = pre[f]; low[aim][0] = low[f][0]; low[aim][1] = low[f][1]; type[aim] = type[f]; } int n, u; int to = (200000<<2)+10, b = 0, ansr; int Query(int l, int r, int rt){ if(ok[rt]){ if(b == 0) { b = to; ansr = r; Copy(b, rt); return 1; } Merge(to+1, to, rt); if(ok[to+1]){ Copy(to, to+1); ansr = r; return 1; } if(l != r){ int m = l+r >> 1; int k = Query(lson); if(k == 1) Query(rson); } return 0; } int m = l+r >> 1; int k = Query(lson); if(k == 1) Query(rson); return 0; } int main(){ scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &v[i]), v[i] += 1; for(int i = 2; i <= n; ++i){ scanf("%d", &u); vc[u].pb(i); } dfs(1); for(int i = 1; i <= n; ++i) Update(v[i], i, 1, n, 1); int q, op, l, r; scanf("%d", &q); while(q--){ scanf("%d", &op); if(op == 1){ scanf("%d%d", &l, &r); swap(v[l], v[r]); Update(v[l], l, 1, n, 1); Update(v[r], r, 1, n, 1); } else { b = 0; Query(1,n,1); printf("%d\n", ansr); } } return 0; }
View Code