bzoj4103 [Thu Summer Camp 2015]异或运算 可持久化trie

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/82078543

Description


给定长度为n的数列X={x1,x2,…,xn}和长度为m的数列Y={y1,y2,…,ym},令矩阵A中第i行第j列的值Aij=xi xor yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij。

对于100%的数据,0<=Xi,Yj<2^31,
1<=u<=d<=n<=1000,
1<=l<=r<=m<=300000,
1<=k<=(d-u+1)*(r-l+1),
1<=p<=500

Solution


考虑n=1的时候怎么做。容易想到建可持久化trie求区间异或上一个数后的第k大
我们发现n很小,于是对m建可持久化trie,用n个指针在trie上分别跳就行了

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define copy(x,t) memcpy(x,t,sizeof(x))
#define fi first
#define se second

typedef std:: pair <int,int> pair;
const int M=300005;
const int N=1005;

int rec[M*34][2],size[M*34],root[M],tot;
int a[N];

pair pos[N];

int read() {
    int x=0,v=1; char ch=getchar();
    for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
    for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
    return x*v;
}

void ins(int pre,int &now,int v) {
    int x=now=++tot;
    drp(i,31,0) {
        copy(rec[x],rec[pre]);
        int tar=(v&(1<<i))!=0;
        rec[x][tar]=++tot;
        x=rec[x][tar]; pre=rec[pre][tar];
        size[x]=size[pre]+1;
    }
}

int query(int l,int r,int pre,int now,int k) {
    int ret=0;
    rep(i,l,r) pos[i]=pair(pre,now);
    drp(i,31,0) {
        int sum=0;
        rep(j,l,r) {
            int tar=(a[j]&(1<<i))!=0;
            sum+=size[rec[pos[j].se][!tar]]-size[rec[pos[j].fi][!tar]];
        }
        if (k<=sum) {
            rep(j,l,r) {
                int tar=(a[j]&(1<<i))!=0;
                pos[j].fi=rec[pos[j].fi][!tar];
                pos[j].se=rec[pos[j].se][!tar];
                ret|=1<<i;
            }
        } else {
            k-=sum;
            rep(j,l,r) {
                int tar=(a[j]&(1<<i))!=0;
                pos[j].fi=rec[pos[j].fi][tar];
                pos[j].se=rec[pos[j].se][tar];
            }
        }
    }
    return ret;
}

int main(void) {
    int n=read(),m=read();
    rep(i,1,n) a[i]=read();
    rep(i,1,m) ins(root[i-1],root[i],read());
    for (int T=read();T--;) {
        int u=read(),d=read(),l=read(),r=read(),k=read();
        printf("%d\n", query(u,d,root[l-1],root[r],k));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/82078543