校內模擬賽 SovietPower Play With Amstar

SovietPower Play With Amstar

題意:ios

  一棵二叉樹,每次詢問一條路徑上的路徑和,初始每一個點有一個權值1,詢問後權值變爲0。$n \leq 10^7,m\leq10^6$git

分析:優化

  首先樹鏈剖分+線段樹可作,$O(mlog^2)$,複雜度太大。spa

  而後並查集縮點,樹剖求lca,$O(n+mlogn)$。能夠被卡一個subtask。code

  考慮咱們並查集的過程當中是不斷往上跳,跳到相等時結束,這個點多是lca,也可能不是,須要判斷一下,考慮優化這個判斷。blog

  二叉樹的前序遍歷有一個性質:兩個點的lca在他們中間。因而按照這個性質就能夠$O(n+m)$了。string

代碼:it

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cctype>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#define Swap(l, r) l ^= r, r ^= l, l ^= r
#define fore(i, u, v) for (int i = head[u], v = e[i].to; i; i = e[i].nxt, v = e[i].to) 
using namespace std;
typedef long long LL;

char buf[10000000], *p1 = buf, *p2 = buf;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++)
inline int read() {
    int x=0,f=1;char ch=nc();for(;!isdigit(ch);ch=nc())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=nc())x=x*10+ch-'0';return x*f;
}

const int N = 10000005;
int ls[N], rs[N], fa[N], pos[N], f[N], dep[N];
int Root, Index;

inline void add_edge(int u,int v) {
    if (v == Root || u == 0) return ;
    if(!ls[u]) ls[u] = v;
    else rs[u] = v; 
}
void dfs(int u) {
    if (!u) return ;
    dep[u] = dep[fa[u]] + 1;
    dfs(ls[u]);
    pos[u] = ++Index;
    dfs(rs[u]);
}
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
int solve(int u,int v) {
    int ans = 0, l = pos[u], r = pos[v]; l > r ? Swap(l, r) : l;
    u = find(u), v = find(v);
    while (u != v) ans ++, dep[u] > dep[v] ? u = f[u] = find(fa[u]) : v = f[v] = find(fa[v]);
    if (pos[u] >= l && pos[u] <= r) ans ++, f[u] = find(fa[u]), u = find(u);
    return ans;
}
int main() {
    read();int opt = read(), n = read(), m = read(); Root = read();
    for (int i = 1; i <= n; ++i) fa[i] = read(), add_edge(fa[i], i);
    dfs(Root);
    for (int i = 1; i <= n; ++i) f[i] = i;
    int lastans = 0, u, v;
    while (m --) {
        u = read(), v = read();
        u = (u ^ (lastans * opt)) % n + 1, v = (v ^ (lastans * opt)) % n + 1;
        lastans = solve(u, v);
        printf("%d\n", lastans);
    }
    return 0;
}
相關文章
相關標籤/搜索