HDU 5390 tree

给出一棵 n(10w) 的有根树。共 m(10w) 个操作:
0 u v - au=v ( ai109 )
1 u 询问点u到根的路径上的点与u点权异或和的最大值

Trie+分治+线段树
PS:也许将空间复杂度降至O(nw)的分治很惊艳,然而最让我耳目一新的是标记不下传的线段树。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pi acos(-1)
#define inf (1<<30)
#define INF (1<<62)
#define y1 bflaisfnmasf
#define y2 fsafgmalg
#define tm afnsjkf
#define j1 sfakf
#define j2 fasndfkas
#define fi first
#define se second
#define CLR(x,f) memset(x,f,sizeof(x))
#define CPY(x,y) memcpy(x,y,sizeof(x))
#define prt(x) cout<<#x<<":"<
#define prtn(x) cout<<#x<<":"<
#define huh(x) printf("--------case(%d)--------\n",x)
#define travel(x) for(Edge *e=h[x];e;e=e->n)
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
typedef pair<int,ii> iii;

const int M=100005;
int last[M],ecnt,n,m;
struct Edge{
    int to,nxt;
    Edge(){}
    Edge(int to_,int nxt_):to(to_),nxt(nxt_){}
}edge[M];
void ins(int u,int v){
    edge[ecnt]=Edge(v,last[u]);last[u]=ecnt++;
}

int lx[M],rx[M],dfs_clock;
void dfs(int x){
    lx[x]=++dfs_clock;
    for(int i=last[x];i!=-1;i=edge[i].nxt)
        dfs(edge[i].to);
    rx[x]=dfs_clock;
}

struct node{
    int id,val,det;
    node(){}
    node(int id_,int val_,int det_):id(id_),val(val_),det(det_){}
};

struct Trie{
    static const int N=M*25;
    int root,tot;
    int c[N][2],sz[N];//
    int q[32];
    int newnode(){
        ++tot;
        c[tot][0]=c[tot][1]=sz[tot]=0;
        return tot;
    }
    void init(){
        tot=0;
        root=newnode();
    }
    void update(int x,int f){
        for(int i=0;i<31;i++,x>>=1)q[30-i]=x&1;
        int pre=root;
        sz[pre]+=f;
        for(int i=0;i<31;i++){
            if(!c[pre][q[i]])c[pre][q[i]]=newnode();
            pre=c[pre][q[i]];
            sz[pre]+=f;
        }
    }
    int calc(int x){
        if(!sz[root])return 0;
        for(int i=0;i<31;i++,x>>=1)q[30-i]=x&1;
        int ans=0,pre=root;
        for(int i=0;i<31;i++){
            if(c[pre][q[i]^1]&&sz[c[pre][q[i]^1]]){
                pre=c[pre][q[i]^1];
                ans|=1<<30-i;
            }
            else pre=c[pre][q[i]];
        }
        return ans;
    }
}trie;

int ans[M];
struct Segment{
    vectorv[M<<2];
    void build(int x,int l,int r){
        v[x].clear();
        if(l==r)return;
        int mid=l+r>>1;
        build(x<<1,l,mid);
        build(x<<1|1,mid+1,r);
    }
    void update(int x,int l,int r,int L,int R,node t){
        if(L<=l&&r<=R){
            v[x].push_back(t);
            return;
        }
        int mid=l+r>>1;
        if(L<=mid)update(x<<1,l,mid,L,R,t);
        if(R>mid)update(x<<1|1,mid+1,r,L,R,t);
    }
    void query(int x,int l,int r,int to,node t){
        v[x].push_back(t);
        if(l==r)return;
        int mid=l+r>>1;
        if(to<=mid)query(x<<1,l,mid,to,t);
        else query(x<<1|1,mid+1,r,to,t);
    }
    void solve(int x,int l,int r){
        if(v[x].size()){
            trie.init();
            node t;
            for(int i=0;ix].size();i++){
                t=v[x][i];
                if(t.id){
                    ans[t.id]=max(ans[t.id],trie.calc(t.val));
                    /*query*/
                }
                else{
                    trie.update(t.val,t.det);
                    /*update*/
                }
            }
        }
        if(l==r)return;
        int mid=l+r>>1;
        solve(x<<1,l,mid);
        solve(x<<1|1,mid+1,r);
    }
}sgm;

int num[M];
void solve(){
    scanf("%d%d",&n,&m);
    memset(last,-1,n+1<<2);
    ecnt=dfs_clock=0;
    for(int f,i=2;i<=n;i++){
        scanf("%d",&f);
        ins(f,i);
    }
    dfs(1);
    sgm.build(1,1,n);
    node t;
    for(int i=1;i<=n;i++){
        scanf("%d",&num[i]);
        t=node(0,num[i],1);
        sgm.update(1,1,n,lx[i],rx[i],t);
    }
    for(int u,v,w,i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        node t;
        if(u==0){
            scanf("%d",&w);
            t=node(0,num[v],-1);
            sgm.update(1,1,n,lx[v],rx[v],t);

            num[v]=w;

            t=node(0,num[v],1);
            sgm.update(1,1,n,lx[v],rx[v],t);
            ans[i]=-1;//没必要回答 
        }
        else{
            t=node(i,num[v],0);
            sgm.query(1,1,n,lx[v],t);           
            //* sgm.update(1,1,n,v,rx[v],t);

            ans[i]=0;
        }
    }
    sgm.solve(1,1,n);

    for(int i=1;i<=m;i++)
        if(ans[i]!=-1)printf("%d\n",ans[i]);
}

int main(){
    int cas;scanf("%d",&cas);
    while(cas--)solve();
    return 0;
}
/*
only query 
1
10 1
1 1 2 2 3 1 2 3 5
23512 460943 835901 491571 399045 488033 187367 800843 734984 106134
1 6
ans=766812
*/

你可能感兴趣的:(Trie,分治,线段树)