Cattle-off practice match 58 F

The meaning of problems

Request with modified single-point between any two points of the sub-tree path length and XOR.
All equal path length and the XOR path.

answer

Simple simulate what can be found.
An odd number, the answer is even dots and XOR.
With even lower, that is normal and XOR.

XOR and even dots are also easy to handle.
It points to the depth of parity Fenwick tree.

But this is for the chain, can not be directly d f s dfs sequence, what needs to split.
But I will not, so to learn a bit.

Simple means:
a child node of the largest sub-tree as heavy son.
Every priority son ran heavy, can make d f s dfs sequence of the heavy chain are continuous.
With this feature, when we treated each jump chain head, and finally continue processing ask.

This wherein: the complexity of the tree is split chain n l The g 2 n nlog ^ 2n
but I have two questions:
Why is the complexity of the guarantee, and why jump the first jump, when the first large chain or depth d f s dfs sequence large.

But now's not the point, I tried to get the pigeon (forced to learn the tree section, recently obviously get in graph theory)

Single-point update, three segment tree can be.

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

const int maxn = 2e5+100;

vector<int>G[maxn];

int sz[maxn],son[maxn],dep[maxn];
int dfn[maxn],top[maxn],fa[maxn];
int A[maxn],cnt,n,m;

//剖分
void dfs1(int u,int pre){
    dep[u]=dep[pre]+1;
    sz[u]=1,fa[u]=pre;
    int s=0;
    for(auto v:G[u]){
        if(v==pre)continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(sz[v]>s)son[u]=v,s=sz[v];
    }
}

void dfs2(int u,int tr_top){
    dfn[u]=++cnt;
    top[u]=tr_top;
    if(son[u])dfs2(son[u],tr_top);
    for(auto v:G[u]){
        if(v==fa[u]||v==son[u])continue;
        dfs2(v,v);
    }
}

//树状数组
int C[maxn][3];

int lowbit(int x){return (x&(-x));}
void change(int x,int d,int id){for(int i=x;i<=n;i+=lowbit(i))C[i][id]^=d;}
int query(int x,int id){if(x==0)return 0;int ret=0;for(int i=x;i;i-=lowbit(i))ret^=C[i][id];return ret;}

//树链剖分更新
void update(int x,int c){
    int val=A[x]^c;
    change(dfn[x],val,dep[x]%2);
    change(dfn[x],val,2);
    if(c)A[x]=c;
}

int query(int l,int r,int id){
    int ans=0,now;
    if(dep[l]%2!=dep[r]%2)now=2;
    else now=(dep[l]%2)^1;
    //cout<<id<<"?"<<endl;
    while(top[l]!=top[r]){
        if(dep[l]<dep[r])swap(l,r);
        ans^=query(dfn[l],now)^query(dfn[top[l]]-1,now);
      //  cout<<dfn[l]<<" "<<dfn[top[l]]-1<<endl;
        l=fa[top[l]];
    }
//    cout<<l<<" "<<r<<" "<<dep[l]%2<<" "<<dep[r]%2<<endl;
    if(dfn[l]<=dfn[r])ans^=query(dfn[r],now)^query(dfn[l]-1,now);
    else ans^=query(dfn[l],now)^query(dfn[r]-1,now);
    //cout<<dfn[l]<<" "<<dfn[r]<<endl;
    return ans;
}

int main(){
    cin>>n>>m;
    FOR(i,1,n)scanf("%d",&A[i]);
    FOR(i,1,n-1){
        int u,v;scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1,0);
    dfs2(1,1);
    FOR(i,1,n){
     //   cout<<i<<" "<<fa[i]<<" "<<sz[i]<<" "<<son[i]<<" "<<dep[i]<<" "<<dfn[i]<<" "<<top[i]<<endl;
    }
    FOR(i,1,n)update(i,0);
    FOR(i,1,m){
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(op==1)update(l,r);
        else printf("%d\n",query(l,r,i));
    }
    //cout<<dfn[2]<<endl;
   // cout<<query(dfn[2],2)-query(dfn[2]-1,2)<<endl;
}

Published 203 original articles · won praise 17 · views 20000 +

Guess you like

Origin blog.csdn.net/mxYlulu/article/details/104905974