【BZOJ 4103】 4103: [Thu Summer Camp 2015]异或运算 (可持久化Trie)

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

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 474  Solved: 258

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

Source

鸣谢佚名上传

【分析】

  要膜一膜Po姐:

  好了,这个是。。。异或运算。每一位的运算都和下一位无关的。

  当n=1,你只要根据m个数建一个可持久化TRIE。然后询问的时候就试着填1看看足不足k什么的。

  跟平时不一样的是,现在你是手上拿着个a1之后询问的,你只要每次看一看a1这一位是什么,然后判断填1还是0,如果a1这一位是1就要0、1互换一下嘛。。

  然后n不等于1,其实也很小,相当于1000个TRIE?当然是不用建1000个TRIE的【你也建不了吧?

  只是你现在手上拿着1000个ai,一起询问什么的。。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #define Maxn 1010
  8 #define Maxm 300010
  9 #define Maxd 30
 10
 11 int a[Maxn];
 12
 13 int rt[Maxm],tot=0;
 14 struct node {int lc,rc,cnt;}tr[Maxm*32];
 15
 16 void add(int id,int x)
 17 {
 18     rt[id]=++tot;int y=rt[id-1];
 19     int nw=rt[id];
 20     for(int i=Maxd;i>=0;i--)
 21     {
 22         int ind=x>>i;x&=(1<<i)-1;
 23         if(!ind)
 24         {
 25             tr[nw].lc=++tot;
 26             tr[tot].cnt=tr[tr[y].lc].cnt+1;
 27             tr[nw].rc=tr[y].rc;
 28             nw=tr[nw].lc;y=tr[y].lc;
 29         }
 30         else
 31         {
 32             tr[nw].rc=++tot;
 33             tr[tot].cnt=tr[tr[y].rc].cnt+1;
 34             tr[nw].lc=tr[y].lc;
 35             nw=tr[nw].rc;y=tr[y].rc;
 36         }
 37     }
 38 }
 39
 40 int nl[Maxn],nr[Maxn];
 41 int query(int ll,int rr,int l,int r,int k)
 42 {
 43     int ans=0;
 44     // l=rt[l-1];r=rt[r];
 45     for(int i=ll;i<=rr;i++) nl[i]=rt[l-1],nr[i]=rt[r];
 46     for(int i=Maxd;i>=0;i--)
 47     {
 48         int x=0;
 49         for(int j=ll;j<=rr;j++)
 50         {
 51             int y=a[j]&(1<<i);y>>=i;
 52             if(y==0) x+=tr[tr[nr[j]].lc].cnt-tr[tr[nl[j]].lc].cnt;
 53             else x+=tr[tr[nr[j]].rc].cnt-tr[tr[nl[j]].rc].cnt;
 54         }
 55         if(x>=k)
 56         {
 57             l=tr[l].lc;r=tr[r].lc;
 58             for(int j=ll;j<=rr;j++)
 59             {
 60                 int y=a[j]&(1<<i);y>>=i;
 61                 if(y==0) nl[j]=tr[nl[j]].lc,nr[j]=tr[nr[j]].lc;
 62                 else nl[j]=tr[nl[j]].rc,nr[j]=tr[nr[j]].rc;
 63             }
 64         }
 65         else
 66         {
 67             k-=x;
 68             ans|=1<<i;
 69             for(int j=ll;j<=rr;j++)
 70             {
 71                 int y=a[j]&(1<<i);y>>=i;
 72                 if(y==0) nl[j]=tr[nl[j]].rc,nr[j]=tr[nr[j]].rc;
 73                 else nl[j]=tr[nl[j]].lc,nr[j]=tr[nr[j]].lc;
 74             }
 75         }
 76     }
 77     return ans;
 78 }
 79
 80 int main()
 81 {
 82     int n,m;
 83     scanf("%d%d",&n,&m);
 84     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
 85     for(int j=1;j<=m;j++)
 86     {
 87         int b;
 88         scanf("%d",&b);
 89         add(j,b);
 90     }
 91     int q;
 92     scanf("%d",&q);
 93     for(int i=1;i<=q;i++)
 94     {
 95         int ll,rr,l,r,k;
 96         scanf("%d%d%d%d%d",&ll,&rr,&l,&r,&k);
 97         k=(rr-ll+1)*(r-l+1)-k+1;
 98         printf("%d\n",query(ll,rr,l,r,k));
 99     }
100     return 0;
101 }

最近已经RE至死。。。

数组开少了2。。。

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 using namespace std;
  7 #define Maxn 1010
  8 #define Maxm 300010
  9 #define Maxd 30
 10
 11 int a[Maxn];
 12
 13 int rt[Maxm],tot=0;
 14 struct node {int lc,rc,cnt;}tr[Maxm*32];
 15
 16 void add(int id,int x)
 17 {
 18     rt[id]=++tot;int y=rt[id-1];
 19     int nw=rt[id];
 20     for(int i=Maxd;i>=0;i--)
 21     {
 22         int ind=x>>i;x&=(1<<i)-1;
 23         if(!ind)
 24         {
 25             tr[nw].lc=++tot;
 26             tr[tot].cnt=tr[tr[y].lc].cnt+1;
 27             tr[nw].rc=tr[y].rc;
 28             nw=tr[nw].lc;y=tr[y].lc;
 29         }
 30         else
 31         {
 32             tr[nw].rc=++tot;
 33             tr[tot].cnt=tr[tr[y].rc].cnt+1;
 34             tr[nw].lc=tr[y].lc;
 35             nw=tr[nw].rc;y=tr[y].rc;
 36         }
 37     }
 38 }
 39
 40 int nl[Maxn],nr[Maxn];
 41 int query(int ll,int rr,int l,int r,int k)
 42 {
 43     int ans=0;
 44     // l=rt[l-1];r=rt[r];
 45     for(int i=ll;i<=rr;i++) nl[i]=rt[l-1],nr[i]=rt[r];
 46     for(int i=Maxd;i>=0;i--)
 47     {
 48         int x=0;
 49         for(int j=ll;j<=rr;j++)
 50         {
 51             int y=a[j]&(1<<i);y>>=i;
 52             if(y==0) x+=tr[tr[nr[j]].lc].cnt-tr[tr[nl[j]].lc].cnt;
 53             else x+=tr[tr[nr[j]].rc].cnt-tr[tr[nl[j]].rc].cnt;
 54         }
 55         if(x>=k)
 56         {
 57             l=tr[l].lc;r=tr[r].lc;
 58             for(int j=ll;j<=rr;j++)
 59             {
 60                 int y=a[j]&(1<<i);y>>=i;
 61                 if(y==0) nl[j]=tr[nl[j]].lc,nr[j]=tr[nr[j]].lc;
 62                 else nl[j]=tr[nl[j]].rc,nr[j]=tr[nr[j]].rc;
 63             }
 64         }
 65         else
 66         {
 67             k-=x;
 68             ans|=1<<i;
 69             for(int j=ll;j<=rr;j++)
 70             {
 71                 int y=a[j]&(1<<i);y>>=i;
 72                 if(y==0) nl[j]=tr[nl[j]].rc,nr[j]=tr[nr[j]].rc;
 73                 else nl[j]=tr[nl[j]].lc,nr[j]=tr[nr[j]].lc;
 74             }
 75         }
 76     }
 77     return ans;
 78 }
 79
 80 int main()
 81 {
 82     int n,m;
 83     scanf("%d%d",&n,&m);
 84     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
 85     for(int j=1;j<=m;j++)
 86     {
 87         int b;
 88         scanf("%d",&b);
 89         add(j,b);
 90     }
 91     int q;
 92     scanf("%d",&q);
 93     for(int i=1;i<=q;i++)
 94     {
 95         int ll,rr,l,r,k;
 96         scanf("%d%d%d%d%d",&ll,&rr,&l,&r,&k);
 97         k=(rr-ll+1)*(r-l+1)-k+1;
 98         printf("%d\n",query(ll,rr,l,r,k));
 99     }
100     return 0;
101 }

2017-04-08 14:47:45

时间: 2024-11-07 01:54:26

【BZOJ 4103】 4103: [Thu Summer Camp 2015]异或运算 (可持久化Trie)的相关文章

【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行,每行

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

一看数据范围,n很小m很大,对长的那一维建可持久化线段树,另一维暴力枚举 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt,tot,p; 7 int rt[300005]; 8 int x[2005]; 9 int y[300005]; 10 struct Trie{ 11 in

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

内存限制:512 MiB 时间限制:1000 ms 题目描述 给定长度为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. 输入格式 第一行包含两个正整数n,m,分别表示两个数列的长度 第二行包含n个非负整数xi 第三行包含m个非负整数yj 第四行包含一个正整数p,表示询问次数 随后p行,每行均包含5个正整数,用来描述一次询问,每行

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

试题描述 给定长度为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. 输入 第一行包含两个正整数n,m,分别表示两个数列的长度 第二行包含n个非负整数xi 第三行包含m个非负整数yj 第四行包含一个正整数p,表示询问次数 随后p行,每行均包含5个正整数,用来描述一次询问,每行包含五个正整数u,d,l,r,k,含义如题意所述. 输

【BZOJ 4104】【Thu Summer Camp 2015】解密运算

http://www.lydsy.com/JudgeOnline/problem.php?id=4104 网上题解满天飞,我也懒得写了 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 200003; int in() { int k = 0, fh = 1; char c = getchar(); for(; c < '0' || c

bzoj4103异或运算 可持久化trie树

要去清华冬令营了,没找到2016年的题,就先坐一坐15年的. 因为n很小,就按照b串建可持久化trie树,a串暴力枚举. 其他的直接看代码. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { int x=0,f=1,ch=getchar(); while(ch<'0'||ch

【BZOJ 4104】 4104: [Thu Summer Camp 2015]解密运算 (智商)

4104: [Thu Summer Camp 2015]解密运算 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 370  Solved: 237 Description 对于一个长度为N的字符串,我们在字符串的末尾添加一个特殊的字符".".之后将字符串视为一个环,从位置1,2,3,...,N+1为起点读出N+1个字符,就能得到N+1个字符串. 比如对于字符串"ABCAAA",我们可以得到这N+1个串: ABCAAA.

[Thu Summer Camp 2015]解密运算

4104: [Thu Summer Camp 2015]解密运算 Time Limit: 10 Sec  Memory Limit: 512 MB Description 对于一个长度为N的字符串,我们在字符串的末尾添加一个特殊的字符".".之后将字符串视为一个环,从位置1,2,3,...,N+1为起点读出N+1个字符,就能得到N+1个字符串. 比如对于字符串“ABCAAA”,我们可以得到这N+1个串: ABCAAA. BCAAA.A CAAA.AB AAA.ABC AA.ABCA A

[Luogu P4735]最大异或和(可持久化Trie)

[Luogu P4735]最大异或和(可持久化Trie) 题面 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 分析 维护\(sum[i]=sum[i-1] \ \text{XOR} \ a[i]\),那么答案就是\(sum[