zoukankan      html  css  js  c++  java
  • HDU 6191 Query on A Tree(字典树+离线)

    Query on A Tree

    Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
    Total Submission(s): 1238    Accepted Submission(s): 444


    Problem Description
    Monkey A lives on a tree, he always plays on this tree.

    One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.

    Monkey A gave a value to each node on the tree. And he was curious about a problem.

    The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).

    Can you help him?
     

    Input
    There are no more than 6 test cases.

    For each test case there are two positive integers n and q, indicate that the tree has n nodes and you need to answer q queries.

    Then two lines follow.

    The first line contains n non-negative integers $V_1,V_2,cdots,V_n$, indicating the value of node i.

    The second line contains n-1 non-negative integers $F_1,F_2,cdots\,F_{n-1}$, $F_i$ means the father of node $i+1$.

    And then q lines follow.

    In the i-th line, there are two integers u and x, indicating that the node you pick should be in the subtree of u, and x has been described in the problem.

    $2 leq n,q leq 10^5$

    $0 leq V_i leq 10^9$

    $1 leq F_i leq n$, the root of the tree is node 1.

    $1 leq u leq n,0 leq x leq 10^9$
     

    Output
    For each query, just print an integer in a line indicating the largest result.
     

    Sample Input
    2 2 1 2 1 1 3 2 1

    很久都没写过博客了qwq,重新写起了久违的博客。

    其实前几天才做了18年的湖北省赛的网络同步赛,I题完全就是这个题的弱化版,而且数据还很水,被我写错了一个地方还AC了。

    经人提点后,才发现对于一颗树上的每一个节点以及他的子节点经过DFS序可以构成一个连续的区间(转换成区间后就完全就是跟湖北省赛的I一模一样的问题,实在是无力吐槽),但是有一个需要注意的地方,dfs序的标号与原先的节点标号是不一样的,所以需要用一个数组记录他们之间的映射关系,然后通过离线即可解决问题。

    关于离线的具体操作,就是将所有的询问保存下来,然后按照左端点的位置从大到小排序,然后从大到小插入大于每个询问值对应的二进制到01字典树中,同时更新或者标记对应点的id,如果查询时遇到id的值小于等于询问的右区间即可取得区间异或的最大值,否则反之。

    #include <algorithm>
    #include <bitset>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <deque>
    #include <iostream>
    #include <istream>
    #include <iterator>
    #include <list>
    #include <map>
    #include <new>
    #include <ostream>
    #include <queue>
    #include <set>
    #include <sstream>
    #include <stack>
    #include <string>
    #include <vector>
    using namespace std;
    # ifdef __GNUC__
    # if __cplusplus > 199711L
    # include <unordered_set>
    # include <unordered_map>
    # else
    #include <tr1/unordered_map>
    #include <tr1/unordered_set>
    using tr1::unordered_map;
    using tr1::unordered_set;
    # endif
    # else
    # include <unordered_map>
    # include <unordered_set>
    # endif
    #define    FOR(i,a,n)       for(register int i=(a),_=(n)+1;i<_;++i)
    #define    FIR(i,n,a)       for(register int i=(n),_=(a)-1;i>_;--i)
    #define    all(a)           (a).begin(),(a).end()
    #define    vlb(a,n)         (lower_bound(all(a),n)-(a).begin())
    #define    vub(a,n)         (upper_bound(all(a),n)-(a).begin())
    #define    vlbx(a,n)        ((a)[(lower_bound(all(a),n)-(a).begin())])
    #define    vubx(a,n)        ((a)[(upper_bound(all(a),n)-(a).begin())])
    #define    reunique(a)      (a).resize(unique(all(a))-(a).begin())
    #define    mem(a,b)         memset((a),(b),sizeof(a))
    #define    sz(x)            (int((x).size()))
    #define    lowbit(x)        ((x)&(-x))
    #define    lch              p<<1,l,mid
    #define    rch              p<<1|1,mid+1,r
    #define    ll               (p<<1)
    #define    rr               (p<<1|1)
    #define    queues           priority_queue
    #define    pb               push_back
    #define    mp(a,b)          make_pair((a),(b))
    #define    lb               lower_bound
    #define    ub               upper_bound
    #define    ff               first
    #define    ss               second
    //#pragma    comment(linker, "/STACK:1024000000,1024000000")
    //__attribute__((optimize("-O2")))
    typedef    long long        LL;
    typedef    pair<int,int>    PII;
    typedef    pair<LL,LL>      PLL;
    typedef    vector<bool>     VB;
    typedef    vector<int>      VI;
    typedef    vector<LL>       VL;
    typedef    vector<PII>      VII;
    typedef    vector<PLL>      VLL;
    // STL other **************************************************************************************
    template<class T,class U>inline istream& operator >> (istream& os,pair<T,U>& p) { return os>>p.first>>p.second; }
    template<class T,class U>inline pair<T,U> operator + (const pair<T,U>& p1,const pair<T,U>& p2) { return mp(p1.ff+p2.ff,p1.ss+p2.ss); }
    template<class T,class U>inline pair<T,U>& operator += (pair<T,U>& p1,const pair<T,U>& p2) { p1.ff+=p2.ff,p1.ss+=p2.ss; return p1; }
    template<class T,class U>inline pair<T,U> operator - (const pair<T,U>& p1,const pair<T,U>& p2) { return mp(p1.ff-p2.ff,p1.ss-p2.ss); }
    template<class T,class U>inline pair<T,U>& operator -= (pair<T,U>& p1,const pair<T,U>& p2) { p1.ff-=p2.ff,p1.ss-=p2.ss; return p1; }
    // Useful constants *******************************************************************************
    
    const int       primes[7] = {24443, 100271, 1000003, 1000333, 5000321, 98765431, 1000000123};
    const int       dx[]= { 0, 1, 0,-1, 0, 1,-1, 1,-1};
    const int       dy[]= {-1, 0, 1, 0,-1, 1,-1,-1, 1};
    #define ee      2.718281828459
    #define eps     0.00000001
    #define fftmod  998244353
    #define INF     0x3f3f3f3f
    #define LINF    0xfcfcfcfcfcfcfcfll
    #define MOD     1000000007
    #define pi      3.14159265358979323846l
    
    int teble();
    int main() {
        ios_base::sync_with_stdio(0);
        cin.tie(0);
    #ifndef ONLINE_JUDGE
    //    freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
    #endif
        teble();
        return 0;
    }
    //***************************************************************
    //***************************************************************
    //***************************************************************
    /**________________________code.begin_________________________**/
    
    const int N=1e5+5;
    int a[N],b[N],tot,ans[N];
    PII p[N];
    struct Edge_Node {
        int head[N],cnt;
        struct Edge { int to,next; } edge[N];
        void init() { mem(head,0),cnt=1; }
        void add(int u,int v) {
            edge[cnt]={v,head[u]},head[u]=cnt++;
        }
    } E;
    struct Dictionarie_Tree {
        int tree[N<<5][3],top;
        void init() { mem(tree[0],0),top=1; }
        void ins(int x,int id) {
            int rt,nxt,u,t;
            for(rt=0,t=31;~t;rt=nxt,--t) {
                nxt=tree[rt][u=x>>t&1];
                if(!nxt)mem(tree[top],0),tree[rt][u]=nxt=top++;
                tree[nxt][2]=id;
            }
        }
        int query(int x,int l) {
            int rt,nxt,u,t,ans=0;
            for(rt=0,t=31;~t;rt=nxt,--t) {
                u=x>>t&1,ans<<=1;
                if((nxt=tree[rt][!u])&&tree[nxt][2]<=l)ans+=1;
                else nxt=tree[rt][u];
            }
            return ans;
        }
    } D;
    struct Node {
        int id,x,l,r;
        bool operator < (Node &m) const {
            return l>m.l;
        }
    } node[N];
    
    void init() {
        E.init(),D.init(),tot=0;
    }
    
    void dfs(int x) {
        p[x].ff=++tot,b[tot]=x;
        for(int i=E.head[x];i;i=E.edge[i].next) {
            dfs(E.edge[i].to);
        }
        p[x].ss=tot;
    }
    
    int teble() {
        int n,q,x,y;
        while(cin>>n>>q) {
            init();
            FOR(i,1,n)cin>>a[i];
            FOR(i,2,n)cin>>x,E.add(x,i);
            dfs(1);
            FOR(i,1,q)cin>>x>>y,node[i]={i,y,p[x].ff,p[x].ss};
            sort(node+1,node+n+1);
            int s=n;
            FOR(i,1,q) {
                while(s>=node[i].l)D.ins(a[b[s]],s),--s;
                ans[node[i].id]=D.query(node[i].x,node[i].r);
            }
            FOR(i,1,q)cout<<ans[i]<<endl;
        }
        return 0;
    }
    
    /**_________________________code.end__________________________**/
    //***************************************************************
    //***************************************************************
    //***************************************************************
    /****************************************************************
    **                                                             **
    **  *********   *********   ********    **          *********  **
    **      **      **          **     **   **          **         **
    **      **      **          **     **   **          **         **
    **      **      *********   ********    **          *********  **
    **      **      **          **     **   **          **         **
    **      **      **          **     **   **          **         **
    **      **      *********   ********    *********   *********  **
    **                                                             **
    ****************************************************************/
    
    
  • 相关阅读:
    MySQL练习题
    InnoDB存储引擎+显示数据库引擎
    EMP+DEPT+SALGRADE 表的基本操作2
    EMP+DEPT+SALGRADE 表的基本操作1
    Git的使用
    JavaScript动画实例:旋转的正三角形
    JavaScript动画实例:曲线的绘制
    JavaScript动画实例:螺旋线
    JavaScript图形实例:阿基米德螺线
    JavaScript图形实例:平面镶嵌图案
  • 原文地址:https://www.cnblogs.com/teble/p/8952322.html
Copyright © 2011-2022 走看看