Cattle-off practice match 58 F-XOR TREE (Conclusion + + split tree chain segment tree)

Cattle-off practice match 58 F-XOR TREE (Conclusion + + split tree chain segment tree)

Links: https://ac.nowcoder.com/acm/contest/4090/F
Source: Cattle-off network

XOR TREE

Time limit: C / C ++ 1 second, 2 seconds languages other
space restrictions: C / C ++ 262144K, other languages 524288K
64bit the IO the Format: LLD%

Title Description

A given n {n} n nodes n-1 {n-1} n-1 edges of the tree with weights, the weights i {i} is the i-th node aia_ {i} ai.

Definition point to point u {u} u {v} v v length of the path is point to point u {u} u {v} and exclusive right or all nodes on the shortest path values ​​v v.

Not do a single point path.

You are now required to maintain q {q} q operations:

1 {1} 1 u {u} ux {x} x the point u {u} u modify the weights x {x} x

2 {2} 2 u {u} uv {v} v seek point to point u {u} u v {v} for all sub-path length between XOR and v

Enter a description:

第一行两个整数n,q{n,q}n,q
第二行n个整数表示a1,a2...an{a_{1},a_{2}...a_{n}}a1,a2...an
接下来n-1行每行两个整数ui,vi{u_{i},v_{i}}ui,vi表示ui,vi{u_{i},v_{i}}ui,vi之间有一条边
接下来q行每行三个整数表示一个查询,数据保证对于查询2{2}2,满足u!=v{u!=v}u!=v。

Output Description:

对于每个查询2{2}2输出一行一个整数表示答案

Example 1

Entry

5 3
1 2 3 4 5
1 2
2 3
3 4
4 5
2 1 5
1 2 8
2 1 5

Export

copy

6
12

Explanation

让f(u,v){f(u,v)}f(u,v)表示点u{u}u到点v{v}v最短路径上所有结点的权值的异或和,那么第一个查询的答案为:
f(1,2)⨁f(1,3)⨁f(1,4)⨁f(1,5)⨁f(2,3)⨁f(2,4)⨁f(2,5)⨁f(3,4)⨁f(3,5)⨁f(4,5)=6{f(1,2)\bigoplus f(1,3)\bigoplus f(1,4)\bigoplus f(1,5)\bigoplus f(2,3)\bigoplus f(2,4)\bigoplus f(2,5)\bigoplus f(3,4)\bigoplus f(3,5)\bigoplus f(4,5)=6}f(1,2)⨁f(1,3)⨁f(1,4)⨁f(1,5)⨁f(2,3)⨁f(2,4)⨁f(2,5)⨁f(3,4)⨁f(3,5)⨁f(4,5)=6

其中f(1,4)=1⨁2⨁3⨁4,f(2,5)=2⨁3⨁4⨁5{f(1,4)=1\bigoplus 2\bigoplus 3\bigoplus 4,f(2,5)=2\bigoplus 3\bigoplus 4\bigoplus 5}f(1,4)=1⨁2⨁3⨁4,f(2,5)=2⨁3⨁4⨁5,其它的类似。

Remarks:

1<=u,v<=n,q<=2e5
1<=ai,x<=1e9

Ideas:

Taking into account the nature of the exclusive-OR \ (X \ X = 0 Oplus \) , i.e., a number twice XOR will destructively

After analysis path in each point contribution to find answers:

  • If the length of the path is an odd number of points, then the order is equivalent to all of the even points are recorded once
  • If the path length is an even number of points, then all points are counted once

Parity order each node may be represented by a parity node rooted tree depth.

Then we may wish to establish two node-based dfs sequence of the tree line,

Are only maintains the node weights depth even number (i.e., a weight of 0 odd node), referred to as A tree might,

And maintaining a depth of the node weights odd number, (i.e. the weight to zero even number of nodes), called the B-tree might.

For each inquiry:

If there are an even number of nodes in the chain path, the path the answer is A XOR tree answers the tree path B answers.

If there are an odd number of nodes in the chain path, the path the answer is the answer or answers A tree path B tree, particularly the tree which is determined according to the parity of the endpoint.

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#include <sstream>
#include <bitset>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
const int maxn = 200010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/

int n, m;
int root;
int a[maxn];// 鲁玫脢录碌茫脠篓
int wt[maxn];// 脨脗陆篓卤脿潞脜碌茫脠篓隆拢
int cnt;// 卤脿潞脜脫脙碌脛卤盲脕驴
int top[maxn];// 脣霉脭脷脰脴脕麓碌脛露楼碌茫卤脿潞脜
int id[maxn];//陆脷碌茫碌脛脨脗卤脿潞脜隆拢
std::vector<int> son[maxn];
int SZ[maxn];// 脳脫脢媒麓贸脨隆
int wson[maxn];// 脰脴露霉脳脫
int fa[maxn];// 赂赂陆脷碌茫
int dep[maxn];// 陆脷碌茫碌脛脡卯露脠

void dfs1(int id, int pre, int step) // 脦卢禄陇鲁枚sz,wson,fa,dep
{
    dep[id] = step;
    fa[id] = pre;
    SZ[id] = 1;
    int  maxson = -1;
    for (auto x : son[id])
    {
        if (x != pre)
        {
            dfs1(x, id, step + 1);
            SZ[id] += SZ[x];
            if (SZ[x] > maxson)
            {
                maxson = SZ[x];
                wson[id] = x;
            }
        }
    }

}

//麓娄脌铆鲁枚top[],wt[],id[]
void dfs2(int u, int topf)
{
    id[u] = ++cnt;
    wt[cnt] = a[u];
    top[u] = topf;
    if (!wson[u]) // 脙禄露霉脳脫脢卤脰卤陆脫陆谩脢酶
    {
        return ;
    }
    dfs2(wson[u], topf); // 脧脠麓娄脌铆脰脴露霉脳脫
    for (auto x : son[u])
    {
        if (x == wson[u] || x == fa[u]) //脰禄麓娄脌铆脟谩露霉脳脫
        {
            continue;
        }
        dfs2(x, x); // 脙驴赂枚脟谩露霉脳脫脪脭脳脭录潞脦陋top
    }
}
int lca(int x, int y) {
    for (; top[x] != top[y]; dep[top[x]] > dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]]);
    return dep[x] < dep[y] ? x : y;
}
int dist(int x, int y) {
    int l = lca(x, y);
    return dep[x] + dep[y] - 2 * dep[l];
}

struct node
{
    int l, r;
    int val;
} A[maxn << 2], B[maxn << 2];

void build(node *segment_tree, int rt, int l, int r)
{
    segment_tree[rt].l = l;
    segment_tree[rt].r = r;
    if (l == r)
    {
        return ;
    }
    int mid = (l + r) >> 1;
    build(segment_tree, rt << 1, l, mid);
    build(segment_tree, rt << 1 | 1, mid + 1, r);
}

void pushup(node *segment_tree, int rt)
{
    segment_tree[rt].val = segment_tree[rt << 1].val ^ segment_tree[rt << 1 | 1].val;
}

void modify(node *segment_tree, int rt, int key, int x)
{
    if (segment_tree[rt].l == key && segment_tree[rt].r == key)
    {
        segment_tree[rt].val = x;
        return ;
    }
    int mid = (segment_tree[rt].l + segment_tree[rt].r) >> 1;
    if (key <= mid)
    {
        modify(segment_tree, rt << 1, key, x);
    } else {
        modify(segment_tree, rt << 1 | 1, key, x);
    }
    pushup(segment_tree, rt);
}
int query(node *segment_tree, int rt, int l, int r)
{
    if (l <= segment_tree[rt].l && segment_tree[rt].r <= r)
    {
        return segment_tree[rt].val;
    }
    int mid = segment_tree[rt].l + segment_tree[rt].r >> 1;
    int res = 0;
    if (r > mid)
    {
        res ^= query(segment_tree, rt << 1 | 1, l, r);
    }
    if (l <= mid)
    {
        res ^= query(segment_tree, rt << 1, l, r);
    }
    return res;
}
int qrange(node *segment_tree, int x, int y)
{
    int ans = 0;
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]])
        {
            swap(x, y);
        }
        ans ^= query(segment_tree, 1, id[top[x]], id[x]);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y])
        swap(x, y);
    ans ^= query(segment_tree, 1, id[x], id[y]);
    return ans;
}

int main()
{
//    freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//    freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
    n = readint();
    m = readint();
    repd(i, 1, n)
    {
        a[i] = readint();
    }
    int u, v;
    repd(i, 2, n)
    {
        u = readint();
        v = readint();
        // cin >> u >> v;
        son[u].pb(v);
        son[v].pb(u);
    }
    root = 1;
    dfs1(root, 0, 1);
    dfs2(root, root);
    // build(1, 1, n);
    int op, x, y;
    build(A, 1, 1, n);
    build(B, 1, 1, n);
    repd(i, 1, n)
    {
        if (dep[i] & 1)
        {
            modify(A, 1, id[i], a[i]);
        } else
        {
            modify(B, 1, id[i], a[i]);
        }
    }
    while (m--)
    {
        op = readint();
        x = readint();
        y = readint();
        if (op == 1)
        {
            if (dep[x] & 1)
            {
                modify(A, 1, id[x], y);
            } else
            {
                modify(B, 1, id[x], y);
            }
        } else if (op == 2)
        {
            int d = dist(x, y);
            int ans = 0;
            if (d & 1)
            {
                ans = qrange(A, x, y)^qrange(B, x, y);
            } else
            {
                if (dep[x] & 1)
                {
                    ans = qrange(B, x, y) ;
                } else
                {
                    ans = qrange(A, x, y);
                }
            }
            printf("%d\n", ans );
        }
    }

    return 0;
}

Guess you like

Origin www.cnblogs.com/qieqiemin/p/12387652.html