hdu 5390 tree (tree line sets the trie)

Topic Link

http://acm.hdu.edu.cn/showproblem.php?pid=5390

The meaning of problems

Given a \ (n-\) a little right of the tree nodes, for \ (m \) operations, each operation belong to the following categories:

  • The right to modify the value of a node.
  • For a given node \ (U \) , find the \ (U \) to \ (1 \) taking node on the path \ (V \) , can get \ (val_u⊗val_v \) maximum.
    \ (1≤n, m≤10 ^ 5,0≤val_i≤10 ^ 9 \)

Thinking

Query \ (x \) the impact point on the path to the root node, so a point will affect the answer modify its sub-tree. Consideration by \ (dfs \) order to maintain a tree line, each will modify the update to its \ (dfs \) Order Intervals. XOR find the maximum value will naturally go \ (Trie \) on the tree. So we can use the tree line sets \ (trie \) tree, each node of the tree line to maintain a \ (01 \) trie, every point modify node weights, in its dfs Order Intervals tree that is updated dictionary can. The time complexity is \ (32nlog_2n \) .
Query There are two ways, one is located in modifying a lazy mark, then the query time to push all the way down to the leaf nodes do queries, this method is very large space overhead.
Another mark is not lazy, you can just line segment tree of this node \ (Trie \) tree deletion and insertion, then a single point when asked for each node in the tree line path \ (Trie \ ) trees are greedy solved a maximum value can be.
The second method, then the size of the trie will open to the \ (32nlog_2n \) , will be super memory. Attached is the code of this method

#include<bits/stdc++.h>
using namespace std;
const int maxx = 1e5+10;
vector<int>ma[maxx];
int w[maxx];
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],ans;
    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 p,int q,int x,int c,int rt)
    {
        if(p<=l&&r<=q)
        {
            trie.update(t[rt],x,c);
            return;
        }
        int mid=(l+r)/2;
        if(p<=mid)update(l,mid,p,q,x,c,rt*2);
        if(q>mid)update(mid+1,r,p,q,x,c,rt*2+1);
    }
    void query(int l,int r,int x,int c,int rt)
    {
        ans=max(ans,trie.query(t[rt],c));
        if(l==r)return;
        int mid=(l+r)/2;
        if(x<=mid)query(l,mid,x,c,rt*2);
        else query(mid+1,r,x,c,rt*2+1);
    }
}tree;
int in[maxx],out[maxx],cnt;
void dfs(int u,int fa)
{
    in[u]=++cnt;
    for(int i=0;i<ma[u].size();i++)
    {
        int v=ma[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
    out[u]=cnt;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)ma[i].clear();
        int x;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&x);
            ma[x].push_back(i);
            ma[i].push_back(x);
        }
        cnt=0;
        dfs(1,0);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        trie.init();
        tree.build(1,n,1);
        for(int i=1;i<=n;i++)
            tree.update(1,n,in[i],out[i],w[i],1,1);
        int op,y;
        while(m--)
        {
            scanf("%d",&op);
            if(op==0)
            {
                scanf("%d%d",&x,&y);
                tree.update(1,n,in[x],out[x],w[x],-1,1);
                w[x]=y;
                tree.update(1,n,in[x],out[x],w[x],1,1);
            }
            else
            {
                scanf("%d",&x);
                tree.ans=0;
                tree.query(1,n,in[x],w[x],1);
                printf("%d\n",tree.ans);
            }
        }
    }
    return 0;
}

The second method because the lazy do not mark each node of the tree line are actually independent, so we can consider the segment off the trees do, for each node, the various relevant delete, insert and update answers in the order to do it again on the line. With \ (Vector \) all operations in order to save node, and finally the whole teeth segment tree traversal, every node will clear \ (Trie \) tree, the maintenance operation node sequentially to a \ (Trie \) on. So only need to maintain a \ (Trie \) , to optimize the space complexity to \ (32n \) .

#include<bits/stdc++.h>
using namespace std;
const int maxx = 1e5+10;
vector<int>ma[maxx];
int w[maxx];
struct node{int op,x,c;};
int ans[maxx];
struct Trie
{
    int trie[32*maxx][2],tot;
    int sum[32*maxx];
    void init()
    {
        tot=0;
        trie[0][0]=trie[0][1]=sum[0]=0;
    }
    void update(int x,int c)
    {
        int rt=0;
        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 x)
    {
        int rt=0,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
{
    vector<node>t[maxx<<2];
    void build(int l,int r,int rt)
    {
        t[rt].clear();
        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 p,int q,int x,int c,int rt)
    {
        if(p<=l&&r<=q)
        {
            t[rt].push_back(node{0,x,c});
            return;
        }
        int mid=(l+r)/2;
        if(p<=mid)update(l,mid,p,q,x,c,rt*2);
        if(q>mid)update(mid+1,r,p,q,x,c,rt*2+1);
    }
    void query(int l,int r,int x,int c,int id,int rt)
    {
        t[rt].push_back(node{1,c,id});
        if(l==r)return;
        int mid=(l+r)/2;
        if(x<=mid)query(l,mid,x,c,id,rt*2);
        else query(mid+1,r,x,c,id,rt*2+1);
    }
    void getans(int l,int r,int rt)
    {
        trie.init();
        for(int i=0;i<t[rt].size();i++)
        {
            int op=t[rt][i].op,x=t[rt][i].x,c=t[rt][i].c;
            if(!op)trie.update(x,c);
            else ans[c]=max(ans[c],trie.query(x));
        }
        if(l==r)return;
        int mid=(l+r)/2;
        getans(l,mid,rt*2);
        getans(mid+1,r,rt*2+1);
    }
}tree;
int in[maxx],out[maxx],cnt;
void dfs(int u,int fa)
{
    in[u]=++cnt;
    for(int i=0;i<ma[u].size();i++)
    {
        int v=ma[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
    out[u]=cnt;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)ma[i].clear();
        int x;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&x);
            ma[x].push_back(i);
            ma[i].push_back(x);
        }
        cnt=0;
        dfs(1,0);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        trie.init();
        tree.build(1,n,1);
        for(int i=1;i<=n;i++)
            tree.update(1,n,in[i],out[i],w[i],1,1);
        int op,y,q=0;
        while(m--)
        {
            scanf("%d",&op);
            if(op==0)
            {
                scanf("%d%d",&x,&y);
                tree.update(1,n,in[x],out[x],w[x],-1,1);
                w[x]=y;
                tree.update(1,n,in[x],out[x],w[x],1,1);
            }
            else
            {
                scanf("%d",&x);
                ans[++q]=0;
                tree.query(1,n,in[x],w[x],q,1);
            }
        }
        tree.getans(1,n,1);
        for(int i=1;i<=q;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/HooYing/p/12583785.html