2024-04-07

2024-04-07

上午模拟赛一道题都不会,摆摆摆

下午讲数学的人讲的就是一大坨,听不了一点

晚上改上次模拟赛剩下的一道题

xor on tree

树上的操作转化为 dfs 序上的操作

一个集合和某个数的异或的最大值可以用 01 trie 求

子树在 dfs 序上是一段区间,我们要进行的就是区间加入一个数

单点查询

但实际上我们区间插入的时候如果区间包含当前线段就直接 return 了

所以一个点的集合分散在线段树上一个叶子节点到根节点的路径上,往上边跳着求最大就行了

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N=1e5+10;

int n,m;
int w[N];

int root[N<<2];

vector<int> reuse;

struct Trie {
    struct Node {
        int son[2];
        int cnt;
    }tr[N*250];
    int node;
    void delet(int &u) {
        if(tr[u].cnt) return;
        tr[u].son[0]=tr[u].son[1]=0;
        reuse.push_back(u);
        u=0;
    }
    int newnode() {
        if(!reuse.empty()) {
            int p=reuse.back();
            reuse.pop_back();
            return p;
        }
        return ++node;
    }
    void update(int &u,int x,int t,int k) {
        if(!u) {
            u=newnode();
            tr[u]={{0,0},0};
        }
        tr[u].cnt+=t;
        if(k<0) {
            delet(u);
            return;
        }
        update(tr[u].son[(x>>k)&1],x,t,k-1);
        delet(u);
    }
    int query(int u,int x,int k) {
        if(!u||k<0) return 0;
        int t=(x>>k)&1;
        if(tr[u].son[!t]) return (1<<k)+query(tr[u].son[!t],x,k-1);
        else return query(tr[u].son[t],x,k-1);
    }
}trie;

vector<int> sn[N];
int dfn[N],siz[N],idt;

void dfs(int u) {
    siz[u]=1,dfn[u]=++idt;
    for(int i=0;i<sn[u].size();i++) {
        int v=sn[u][i];
        dfs(v);
        siz[u]+=siz[v];
    }
}

int pos[N];

#define ls (u<<1)
#define rs (u<<1|1)

void build(int u,int lft,int rgh) {
    if(lft==rgh) {
        pos[lft]=u;
        return;
    }
    int mid=lft+rgh>>1;
    build(ls,lft,mid),build(rs,mid+1,rgh);
}

void update(int u,int lft,int rgh,int l,int r,int v,int t) {
    if(lft>=l&&rgh<=r) {
        trie.update(root[u],v,t,30);
        return;
    }
    int mid=lft+rgh>>1;
    if(l<=mid) update(ls,lft,mid,l,r,v,t);
    if(r>mid) update(rs,mid+1,rgh,l,r,v,t);
}

int query(int u,int v) {
    int p=pos[u],res=0;
    for(;p;p>>=1) res=max(res,trie.query(root[p],v,30));
    return res;
}

int main() {
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    for(int u=2;u<=n;u++) {
        int fa;
        scanf("%d",&fa);
        sn[fa].push_back(u);
    }
    dfs(1);
    build(1,1,n);
    for(int i=1;i<=n;i++) update(1,1,n,dfn[i],dfn[i]+siz[i]-1,w[i],1);
    for(int i=1;i<=m;i++) {
        int opt;
        scanf("%d",&opt);
        if(opt==0) {
            int k,x;
            scanf("%d%d",&k,&x);
            update(1,1,n,dfn[k],dfn[k]+siz[k]-1,w[k],-1);
            w[k]=x;
            update(1,1,n,dfn[k],dfn[k]+siz[k]-1,w[k],1);
        }
        else {
            int k;
            scanf("%d",&k);
            printf("%d\n",query(dfn[k],w[k]));
        }
    }

    return 0;
}

注意查询的时候要转化成 dfn[k]

今天就写了一道题,我太菜了……

posted @ 2024-04-08 07:33  OrangeStar*  阅读(8)  评论(0编辑  收藏  举报