Luogu6018 [Ynoi2010]Fusion tree

Luogu6018 [Ynoi2010]Fusion tree

\(Trie\)

\(Trie\)树的奇怪标记实在不是很了解,所以做一下这题。

在每个节点上建\(Trie\)树维护子节点信息,单独维护父节点信息。

如何维护异或和?我们可以维护\(Trie\)树上同一深度节点的奇偶性,即可查出每一位是否是\(1\)

处理全局\(+1\)操作,我们考虑从低位到高位建\(Trie\)树,显然\(+1\)是使得第一个\(0\)变成\(1\)\(0\)以前的\(1\)变成\(0\)

我们可以从根节点出发,交换\(0,1\)两棵子树,把\(0\)变成\(1\)就相当于加\(1\)。继续向\(0\)子树(也就是原来的\(1\)子树)递归,就可以完成进位操作,画图很容易明白。

还有单点修改,直接搜索\(Trie\)树即可。

复杂度\(O(n \log n)\)

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 500005
using namespace std;
int n,m,x,y,opt;
int rt[N],f[N];
struct Trie
{
    int tr[N*22][2],tot;
    int fa[N*22],sz[N*22],on[N*22],dep[N][22];
    int ans[N];
    void push_up(int id,int x,int cs)
    {
        if (!x)
            return;
        if (on[x])
        {            
            ans[id]-=dep[id][cs] << cs;
            dep[id][cs]^=1;
            ans[id]+=dep[id][cs] << cs;
        }
        if (cs!=20)
            sz[x]=sz[tr[x][0]]+sz[tr[x][1]];
        push_up(id,fa[x],cs-1);
    }
    void insert(int rt,int x)
    {
        int u=rt;
        for (int i=0;i<=20;++i)
        {
            int son=(x >> i) & 1;
            if (!tr[u][son])
                tr[u][son]=++tot,fa[tot]=u,on[tot]=son;
            u=tr[u][son];
        }
        ++sz[u];
        push_up(rt,u,20);
    }
    void erase(int rt,int x)
    {
        int u=rt;
        for (int i=0;i<=20;++i)
        {
            int son=(x >> i) & 1;
            u=tr[u][son];
        }
        --sz[u];
        push_up(rt,u,20);
    }
    void push_add(int rt,int x,int cs)
    {
        if (!x)
            return;
        ans[rt]-=dep[rt][cs+1] << cs+1;
        dep[rt][cs+1]^=(sz[tr[x][0]] & 1)^(sz[tr[x][1]] & 1);
        ans[rt]+=dep[rt][cs+1] << cs+1;
        swap(tr[x][0],tr[x][1]),on[tr[x][0]]=0,on[tr[x][1]]=1;
        push_add(rt,tr[x][0],cs+1);
    }
}T;
struct edge
{
    int nxt,v;
    edge (int Nxt=0,int V=0)
    {
        nxt=Nxt,v=V;
    }
}e[N << 1];
int tot,fr[N],a[N];
int tag[N];
int getval(int x)
{
    return a[x]+tag[f[x]];
}
void modify(int x,int y)
{
    if (f[x])
        T.erase(rt[f[x]],getval(x));
    a[x]=y-tag[f[x]];
    if (f[x])
        T.insert(rt[f[x]],y);
}
void add(int x,int y)
{
    ++tot;
    e[tot]=edge(fr[x],y),fr[x]=tot;
}
void dfs(int u,int F)
{
    for (int i=fr[u];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (v==F)
            continue;
        f[v]=u;
        T.insert(rt[u],a[v]);
        dfs(v,u);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;++i)
    {
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    for (int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for (int i=1;i<=n;++i)
        rt[i]=++T.tot;
    dfs(1,0);
    for (int i=1;i<=m;++i)
    {
        scanf("%d",&opt);
        if (opt==1)
        {
            scanf("%d",&x);
            if (f[x])
                modify(f[x],getval(f[x])+1);
            T.push_add(x,rt[x],-1);
            ++tag[x];
        } else
        if (opt==2)
        {
            scanf("%d%d",&x,&y);
            modify(x,getval(x)-y);
        } else
        {
            scanf("%d",&x);
            printf("%d\n",T.ans[x]^((!f[x])?0:getval(f[x])));
        }
    }
    return 0;
}
posted @ 2020-11-27 19:01  GK0328  阅读(88)  评论(0编辑  收藏  举报