EOJ Monthly 2020.9 F. 动态树(线段树套字典树)

题目链接

https://acm.ecnu.edu.cn/contest/317/problem/F/

题意

你需要维护一棵动态树,初始状态下仅有一个节点,编号为\(1\),并支持以下操作:
\(Add x y\):插入一个节点,其编号为当前存在的节点数量(包括当前新加入的节点),指定其父节点为\(x\),并添加一条无向边连接新节点和它的父节点,边权为\(y\)
\(Query x y\):查询起点为\(x\)号节点,终点在\(y\)的子树中(包括\(y\)号节点)的最大简单路径异或和(要求路径不经过重复的节点,且起点与终点不同)。

思路


注意\(1\)号节点的字典树需要插入\(0\)

#include<bits/stdc++.h>
using namespace std;
const int maxx = 2e5+10;
struct Trie
{
    int trie[32*20*maxx][2],tot;
    int sum[32*20*maxx];
    void init()
    {
        tot=0;
        trie[0][0]=trie[0][1]=sum[0]=0;
    }
    void update(int rt,int x,int c)
    {
        for(int i=31;i>=0;i--)
        {
            int id=(x>>i)&1;
            if(!trie[rt][id])
            {
                trie[rt][id]=++tot;
                trie[tot][0]=trie[tot][1]=sum[tot]=0;
            }
            rt=trie[rt][id];
            sum[rt]+=c;
        }
    }
    int query(int rt,int x)
    {
        int res=0;
        for(int i=31;i>=0;i--)
        {
            int id=(x>>i)&1;
            if(trie[rt][id^1]&&sum[trie[rt][id^1]])
                rt=trie[rt][id^1],res+=(1<<i);
            else rt=trie[rt][id];
        }
        return res;
    }
}trie;
struct Tree
{
    int t[maxx<<2];
    void build(int l,int r,int rt)
    {
        t[rt]=++trie.tot;
        if(l==r)return;
        int mid=(l+r)/2;
        build(l,mid,rt*2);
        build(mid+1,r,rt*2+1);
    }
    void update(int l,int r,int k,int x,int c,int rt)
    {
        trie.update(t[rt],x,c);
        if(l==r)return;
        int mid=(l+r)/2;
        if(k<=mid)update(l,mid,k,x,c,rt*2);
        else update(mid+1,r,k,x,c,rt*2+1);
    }
    int query(int l,int r,int p,int q,int x,int rt)
    {
        if(p<=l&&r<=q)return trie.query(t[rt],x);
        int mid=(l+r)/2;
        int res=0;
        if(p<=mid)res=max(res,query(l,mid,p,q,x,rt*2));
        if(q>mid)res=max(res,query(mid+1,r,p,q,x,rt*2+1));
        return res;
    }
}tree;
struct edge
{
    int to,val,next;
}e[maxx*2];
int head[maxx],tot;
void add(int u,int v,int w)
{
    e[++tot].to=v,e[tot].val=w;
    e[tot].next=head[u],head[u]=tot;
}
int in[maxx],out[maxx],a[maxx],cnt;
void dfs(int u,int fa)
{
    in[u]=++cnt;
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa)continue;
        a[v]=a[u]^e[i].val;
        dfs(v,u);
    }
    out[u]=cnt;
}
struct node
{
    int op,x,y;
}q[maxx];
int main()
{
    int Q;
    scanf("%d",&Q);
    char op[2];
    int x,y,tmp;
    int n=1;
    for(int i=1;i<=Q;i++)
    {
        scanf("%s%d%d",op,&x,&y);
        tmp=(op[0]=='A'?0:1);
        if(tmp==0)
        {
            ++n;
            add(x,n,y);add(n,x,y);
            q[i]=node{tmp,x,n};
        }
        else q[i]=node{tmp,x,y};
    }
    dfs(1,0);
    trie.init();
    tree.build(1,n,1);
    tree.update(1,n,1,0,1,1);
    for(int i=1;i<=Q;i++)
    {
        if(q[i].op==0)
        {
            tree.update(1,n,in[q[i].y],a[q[i].y],1,1);
        }
        else
        {
            int ans=tree.query(1,n,in[q[i].y],out[q[i].y],a[q[i].x],1);
            printf("%d\n",ans);
        }
    }
    return 0;
}
posted @ 2020-09-28 15:46  灰灰烟影  阅读(164)  评论(0编辑  收藏  举报