zoukankan      html  css  js  c++  java
  • [BZOJ5361]/[HDU6291]对称数

    [BZOJ5361]/[HDU6291]对称数

    题目大意:

    一个(n(nle2 imes10^5))个结点的树,每个结点有一个权值(a_i(a_ile2 imes10^5))(m(mle2 imes10^5))次询问,每次询问((u,v))路径上最小的出现偶数次的数。

    思路:

    对每个权值随机一个unsigned long long作为一个新的权值,树上主席树维护区间异或和。

    询问时在主席树上二分即可。

    源代码:

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    inline int getint() {
        register char ch;
        while(!isdigit(ch=getchar()));
        register int x=ch^'0';
        while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
        return x;
    }
    typedef unsigned long long uint64;
    const int N=2e5+1,logN=40;
    int a[N],v[N],anc[N][logN],dep[N],mex;
    uint64 w[N],hsum[N];
    std::vector<int> e[N];
    inline void add_edge(const int &u,const int &v) {
        e[u].push_back(v);
        e[v].push_back(u);
    }
    inline int lg2(const float &x) {
        return ((unsigned&)x>>23&255)-127;
    }
    class FotileTree {
        #define mid ((b+e)>>1)
        private:
            struct Node {
                uint64 val;
                int left,right;
            };
            Node node[N*logN];
            int sz,new_node(const int &p) {
                node[++sz]=node[p];
                return sz;
            }
        public:
            void reset() {
                sz=0;
            }
            int root[N];
            void insert(int &p,const int &b,const int &e,const int &x) {
                p=new_node(p);
                node[p].val^=w[v[x]];
                if(b==e) return;
                if(x<=mid) insert(node[p].left,b,mid,x);
                if(x>mid) insert(node[p].right,mid+1,e,x);
            }
            int query(const int &p,const int &q,const int &r,const int &s,const int &b,const int &e) const {
                if((node[p].val^node[q].val^node[r].val^node[s].val)==(hsum[e]^hsum[b-1])) return mex;
                if(b==e) return v[b];
                const int tmp=query(node[p].left,node[q].left,node[r].left,node[s].left,b,mid);
                if(tmp==mex) return query(node[p].right,node[q].right,node[r].right,node[s].right,mid+1,e);
                return tmp;
            }
        #undef mid
    };
    FotileTree t;
    void dfs(const int &x,const int &par) {
        anc[x][0]=par;
        dep[x]=dep[par]+1;
        for(register int i=1;i<=lg2(dep[x]);i++) {
            anc[x][i]=anc[anc[x][i-1]][i-1];
        }
        const int p=std::lower_bound(&v[1],&v[v[0]]+1,a[x])-v;
        t.insert(t.root[x]=t.root[par],1,v[0],p);
        for(unsigned i=0;i<e[x].size();i++) {
            const int &y=e[x][i];
            if(y==par) continue;
            dfs(y,x);
        }
    }
    inline int get_lca(int x,int y) {
        if(dep[x]<dep[y]) std::swap(x,y);
        for(register int i=lg2(dep[x]-dep[y]);i>=0;i--) {
            if(dep[anc[x][i]]>=dep[y]) x=anc[x][i];
        }
        if(x==y) return x;
        for(register int i=lg2(dep[x]);i>=0;i--) {
            if(anc[x][i]!=anc[y][i]) {
                x=anc[x][i];
                y=anc[y][i];
            }
        }
        return anc[x][0];
    }
    inline int query(const int &x,const int &y) {
        const int lca=get_lca(x,y);
        return std::min(t.query(t.root[x],t.root[y],t.root[lca],t.root[anc[lca][0]],1,v[0]),mex);
    }
    int main() {
        srand(19961993);
        for(register int T=getint();T;T--) {
            memset(anc,0,sizeof anc);
            const int n=getint(),m=getint();
            for(register int i=1;i<=n;i++) {
                v[i]=a[i]=getint();
                while(w[a[i]]==0) {
                    w[a[i]]=(uint64)rand()*rand()*rand();
                }
            }
            std::sort(&v[1],&v[n]+1);
            v[0]=std::unique(&v[1],&v[n]+1)-v-1;
            for(register int i=mex=1;i<=v[0];i++) {
                hsum[i]=hsum[i-1]^w[v[i]];
                if(v[i]==mex) mex++;
            }
            for(register int i=1;i<n;i++) {
                add_edge(getint(),getint());
            }
            dfs(1,0);
            for(register int i=0;i<m;i++) {
                printf("%d
    ",query(getint(),getint()));
            }
            t.reset();
            for(register int i=1;i<=n;i++) {
                e[i].clear();
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Android开源demo---芒果TV-VIP电影播放器
    实现sqrt()函数
    std::string内容包含双引号
    解决win10 SVN不显示绿色和红色的状态显示标志
    win 10 解决 caps键无法退出大写的问题
    webrtc 编译问题:running depot tools as root is sad 的解决办法
    Linux下运行脚本显示“: /usr/bin/env: "bash ": 没有那个文件或目录
    解决报错:no acceptable C compiler found in $PATH when installing python
    linux 打开文件管理器
    windows打开U盘提示 文件或目录损坏且无法读取 解决办法
  • 原文地址:https://www.cnblogs.com/skylee03/p/9443162.html
Copyright © 2011-2022 走看看