zoukankan      html  css  js  c++  java
  • [SCOI2016] 幸运数字

    题意:

    给定一棵n个点的树,每个点有点权$G_u$。

    你需要回答q次询问,每次询问一条路径$(u,v)$上选一些点的最大异或和。

    $nleq 20000,qleq 200000,G_u leq 2^{60}$。

    题解:

    二合一板子题。写了个树剖发现$O(nlog^{3}{n})$能过,我也不知道咋回事。

    点分治可以做到$O(nlog^{2}n)$,不过我懒得写了。

    小技巧:线性基严重不满,暴力插入的时候判一下是不是0。

    套路:

    • 维护的东西严重不满$ ightarrow$操作时特判一下可以大量减少复杂度。

    代码:

    #include<bits/stdc++.h>
    #define maxn 20005
    #define maxm 65
    #define inf 0x7fffffff
    #define ll long long
    #define rint register ll
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    ll n,m=61,q,hd[maxn],to[maxn<<1],nxt[maxn<<1];
    ll G[maxn],tp[maxn],cnt;
    struct basis{
        ll b[maxm];
        inline void clear(){memset(b,0,sizeof(b));}
        inline void ins(ll x){for(rint i=m-1;i>=0;i--)if((x>>i)&1){if(b[i])x^=b[i];else{b[i]=x;break;}}}
    };
    
    inline ll read(){
        ll x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline void addedge(ll u,ll v){
        to[++cnt]=v,nxt[cnt]=hd[u],hd[u]=cnt;
        to[++cnt]=u,nxt[cnt]=hd[v],hd[v]=cnt;
    }
    
    inline basis merge(basis x,basis y){
        basis res; res=x;
        for(rint i=0;i<m;i++) 
            if(y.b[i]) res.ins(y.b[i]);
        return res; 
    }
    
    struct Segmentree{
        ll dep[maxn],top[maxn],siz[maxn],son[maxn];
        ll fa[maxn],id[maxn],rk[maxn]; 
        basis tr[maxn<<2];
        inline void dfs1(ll u,ll f){
            fa[u]=f,dep[u]=dep[f]+1,siz[u]=1;
            for(rint i=hd[u];i;i=nxt[i]){
                ll v=to[i]; if(v==f) continue;
                dfs1(v,u),siz[u]+=siz[v];
                if(siz[v]>siz[son[u]]) son[u]=v;
            }
        }
        inline void dfs2(ll u,ll t){
            top[u]=t,id[++id[0]]=u,rk[u]=id[0];
            if(son[u]) dfs2(son[u],t);
            for(rint i=hd[u];i;i=nxt[i])
                {ll v=to[i];if(v!=fa[u]&&v!=son[u])dfs2(v,v);}
        }
        inline void build(ll l,ll r,ll k){
            if(l==r){tr[k].ins(G[id[l]]);return;}
            ll mid=l+r>>1;
            build(l,mid,k<<1),build(mid+1,r,k<<1|1);
            tr[k]=merge(tr[k<<1],tr[k<<1|1]);
        }
        inline basis qry(ll x,ll y,ll l,ll r,ll k){
            if(x<=l && r<=y) return tr[k];
            ll mid=l+r>>1;
            if(x<=mid && y>mid) return merge(qry(x,y,l,mid,k<<1),qry(x,y,mid+1,r,k<<1|1));
            else if(x<=mid) return qry(x,y,l,mid,k<<1); 
            else return qry(x,y,mid+1,r,k<<1|1);
        }
        inline basis calc(ll u,ll v){
            basis res; res.clear();
            while(top[u]!=top[v]){
                if(dep[top[u]]<dep[top[v]]) swap(u,v);
                res=merge(res,qry(rk[top[u]],rk[u],1,n,1));
                u=fa[top[u]];
            }
            if(dep[u]>dep[v]) swap(u,v);
            res=merge(res,qry(rk[u],rk[v],1,n,1));
            return res;
        }
    }Tr;
    
    int main(){
        n=read(),q=read();
        for(rint i=1;i<=n;i++) G[i]=read();
        for(rint i=1;i<n;i++){ll u=read(),v=read();addedge(u,v);}
        Tr.dfs1(1,0),Tr.dfs2(1,1),Tr.build(1,n,1);
        while(q--){
            ll u=read(),v=read(),ans=0;
            basis res=Tr.calc(u,v); 
            for(rint i=m-1;i>=0;i--) 
                if((ans^res.b[i])>ans) ans^=res.b[i];
            printf("%lld
    ",ans);
        }
        return 0;
    }
    幸运数字
  • 相关阅读:
    Zookeeper(1)---初识
    golang的一些零散笔记
    ELK使用过程中遇到的一些问题
    ECharts系列:玩转ECharts之常用图(折线、柱状、饼状、散点、关系、树)
    MySQL系列:Docker安装 MySQL提示错误:Access denied for user'root'@'localhost' (using password:yes)
    HTML+CSS系列:登录界面实现
    Apollo系列(二):ASP.NET Core 3.1使用分布式配置中心Apollo
    Apollo系列(一):分布式配置中心Apollo安装(Linux、Docker)
    为你的应用加上skywalking(链路监控)
    工作中,你是如何开始搭建一套容器云环境的呢?
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13285667.html
Copyright © 2011-2022 走看看