zoukankan      html  css  js  c++  java
  • BZOJ 4103: [Thu Summer Camp 2015]异或运算 可持久化trie

    开始想了一个二分+可持久化trie验证,比正解多一个 log  

    仔细思考,你发现你可以直接按位枚举,然后在可持久化 trie 上二分就好了. 

    code: 

    #include <bits/stdc++.h>  
    #define N 700005   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;      
    int n,m,tot,tl,tr;      
    int ch[N*30][2],cnt[N*30],xx[N],yy[N],rt[N],t1[N],t2[N];         
    void insert(int pre,int &x,int v) 
    {
        int now=x=++tot;        
        for(int i=30;i>=0;--i) 
        {
            int o=((v>>i)&1);    
            ch[now][o^1]=ch[pre][o^1];   
            ch[now][o]=++tot;    
            pre=ch[pre][o]; 
            now=ch[now][o];  
            cnt[now]=cnt[pre]+1;   
        }
    }          
    int query(int L,int R,int kth,int len) 
    {
        if(len<0)     return 0;   
        int re=0,cur=1,i; 
        for(cur=1,i=L;i<=R;++i,++cur) 
        {
            int o=((xx[i]>>len)&1);   
            re+=cnt[ch[t2[cur]][o^1]]-cnt[ch[t1[cur]][o^1]];    
        }    
        if(kth<=re) 
        {   
            for(cur=1,i=L;i<=R;++i,++cur)   
            {
                int o=((xx[i]>>len)&1);   
                t1[cur]=ch[t1[cur]][o^1];   
                t2[cur]=ch[t2[cur]][o^1];    
            }   
            return (1<<len)+query(L,R,kth,len-1); 
        } 
        else 
        { 
            for(cur=1,i=L;i<=R;++i,++cur) 
            {
                int o=((xx[i]>>len)&1);   
                t1[cur]=ch[t1[cur]][o];  
                t2[cur]=ch[t2[cur]][o];   
            }  
            return query(L,R,kth-re,len-1);   
        }
    }
    int main() 
    {   
        // setIO("input");   
        int i,j;  
        scanf("%d%d",&n,&m);   
        for(i=1;i<=n;++i)    scanf("%d",&xx[i]);   
        for(i=1;i<=m;++i)    
        {
            scanf("%d",&yy[i]); 
            insert(rt[i-1],rt[i],yy[i]);   
        }        
        int q; 
        scanf("%d",&q); 
        while(q--) 
        {
            int a,b,c,d,k; 
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);              
            tl=tr=0;  
            for(i=a;i<=b;++i)       t1[++tl]=rt[c-1],t2[tl]=rt[d];       
            printf("%d
    ",query(a,b,k,30));               
        }
        return 0;
    }
    

      

  • 相关阅读:
    Android文件操作工具类(转)
    android中的开机自启动
    Android中调用系统所装的软件打开文件(转)
    Android TextView 阴影效果(投影)
    Smart SVN的使用
    iOS 网络开发
    iOS开发XML解析
    iOS infoq资料架构设计漫谈
    iOS 音频视频制作
    iOS 蒲公英第三方打包平台
  • 原文地址:https://www.cnblogs.com/guangheli/p/11935474.html
Copyright © 2011-2022 走看看