zoukankan      html  css  js  c++  java
  • 【BZOJ4103】[Thu Summer Camp 2015]异或运算 可持久化Trie树

    【BZOJ4103】[Thu Summer Camp 2015]异或运算

    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。

    Input

    第一行包含两个正整数n,m,分别表示两个数列的长度

    第二行包含n个非负整数xi
    第三行包含m个非负整数yj
    第四行包含一个正整数p,表示询问次数
    随后p行,每行均包含5个正整数,用来描述一次询问,每行包含五个正整数u,d,l,r,k,含义如题意所述。

    Output

    共p行,每行包含一个非负整数,表示此次询问的答案。

    Sample Input

    3 3
    1 2 4
    7 6 5
    3
    1 2 1 2 2
    1 2 1 3 4
    2 3 2 3 4

    Sample Output

    6
    5
    1

    HINT

     对于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

    题解:由于n和p很小,考虑暴力枚举行。我们将n个x值都拿出来,对于y维护可持久化Trie树,然后将这些x一起放到可持久化Trie树上二分即可。集体做法与主席树的求第k大类似。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,tot,Q;
    struct node
    {
    	int ch[2],siz;
    }s[10000010];
    int v[1010],p[1010],p1[1010],p2[1010],rt[300010];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int insert(int x,int val)
    {
    	int u,tmp=++tot,d,i;
    	for(u=tmp,i=1<<30;i;i>>=1)
    	{
    		d=(val&i)>0,s[u].ch[d]=++tot,s[u].ch[d^1]=s[x].ch[d^1];
    		u=s[u].ch[d],x=s[x].ch[d],s[u].siz=s[x].siz+1;
    	}
    	return tmp;
    }
    int query(int len,int k)
    {
    	int i,j,ret=0,d,dd,sum;
    	for(i=1<<30;i;i>>=1)
    	{
    		for(sum=0,j=1;j<=len;j++)
    		{
    			d=!(p[j]&i);
    			sum+=s[s[p2[j]].ch[d]].siz-s[s[p1[j]].ch[d]].siz;
    		}
    		if(sum>=k)	dd=0,ret|=i;
    		else	dd=1,k-=sum;
    		for(j=1;j<=len;j++)
    		{
    			d=(!(p[j]&i))^dd;
    			p2[j]=s[p2[j]].ch[d],p1[j]=s[p1[j]].ch[d];
    		}
    	}
    	return ret;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,j,a,b,c,d;
    	for(i=1;i<=n;i++)	v[i]=rd();
    	for(i=1;i<=m;i++)	rt[i]=insert(rt[i-1],rd());
    	Q=rd();
    	for(i=1;i<=Q;i++)
    	{
    		a=rd(),b=rd(),c=rd(),d=rd();
    		for(j=a;j<=b;j++)	p[j-a+1]=v[j],p1[j-a+1]=rt[c-1],p2[j-a+1]=rt[d];
    		printf("%d
    ",query(b-a+1,rd()));
    	}
    	return 0;
    }//3 3 1 2 4 7 6 5 3 1 2 1 2 2 1 2 1 3 4 2 3 2 3 4
  • 相关阅读:
    ping 带时间戳
    普通用户使用docker
    docker权限问题Got permission denied while trying
    Linux下离线安装Docker
    Linux启动流程和服务管理(init和systemd)
    CentOS 7 巨大变动之 systemd 取代 SysV的Init
    Linux系统常用的关机或重启命令shutdown、reboot、halt、poweroff、init 0及init 6的联系与区别
    linux的init.d
    linux service命令
    Linux下安装MySQL数据库(压缩包方式安装)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7500232.html
Copyright © 2011-2022 走看看