BZOJ 4103: [Thu Summer Camp 2015]异或运算

来源:互联网 发布:佛山cnc编程最新招聘 编辑:程序博客网 时间:2024/06/09 16:48

第一次打可持久化trie树。。不过貌似不是太难打?
M很大 对M个数来建可持久化trie树 N较小 在询问的时候一起搞就好
不难得出复杂度 O(m32+nq32)

异或这种东西 不难就能想到用trie树 然后统计一下数量 搞一下 求第K大
比如让它尽量大的话 这一位是0就走去1 是1的话就反之

自认为代码还是挺好看的~(为什么我又觉得他有点慢)

#include<bits/stdc++.h>using namespace std;const int N=1002,M=300002,D=30;inline int read(){    char ch=getchar(); int x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}    return x*f;}int a[N],rt[M],tot,lc[M*32],rc[M*32],c[M*32];void add(int id,int x){    rt[id]=++tot; int y=rt[id-1],nw=tot;    for(int i=D;~i;i--){        int u=x>>i; x&=(1<<i)-1;        if(u){            rc[nw]=++tot,c[tot]=c[rc[y]]+1;            lc[nw]=lc[y],nw=tot,y=rc[y];        }        else{            lc[nw]=++tot,c[tot]=c[lc[y]]+1;            rc[nw]=rc[y],nw=tot,y=lc[y];        }    }}int nl[N],nr[N],L,R,l,r,k;void query(){    int ret=0,i;    for(i=L;i<=R;i++)nl[i]=rt[l-1],nr[i]=rt[r];    for(i=D;~i;i--){        int x=0;        for(int j=L;j<=R;j++){            int u=(a[j]>>i)&1;            if(u)x+=c[lc[nr[j]]]-c[lc[nl[j]]];            else x+=c[rc[nr[j]]]-c[rc[nl[j]]];        }        if(x>=k){            for(int j=L;j<=R;j++){                int u=(a[j]>>i)&1;                if(u)nr[j]=lc[nr[j]],nl[j]=lc[nl[j]];                else nr[j]=rc[nr[j]],nl[j]=rc[nl[j]];            }            ret|=(1<<i);        }        else{            k-=x;            for(int j=L;j<=R;j++){                int u=(a[j]>>i)&1;                if(u)nr[j]=rc[nr[j]],nl[j]=rc[nl[j]];                else nr[j]=lc[nr[j]],nl[j]=lc[nl[j]];            }        }    }    printf("%d\n",ret);}int main(){    int n=read(),m=read(),i,x;    for(i=1;i<=n;i++)a[i]=read();    for(i=1;i<=m;i++){        x=read(); add(i,x);    }    int q=read();    while(q--){        L=read(),R=read(),l=read(),r=read(),k=read();        query();    }    return 0;}
1 0
原创粉丝点击