[BZOJ4103][Thu Summer Camp 2015]异或运算 可持久化Trie树

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

Time Limit: 20 Sec  Memory Limit: 512 MB

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.
 
题解:
看到“区间”“k小”几个关键词,我们自然想到了可持久化数据结构
再加上“异或”,那么可持久化Trie没跑了。
我们发现这个数据范围极不平衡……
所以我们考虑对于M建立Trie树,这样for循环扫起来数据比较小,最多只需要同时扫2000棵Trie即可
这样我们把n里面所有点,以及对应区间的Trie都存进vector或者其他容器里面,然后处理即可。和主席树非常相似。
代码见下:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 using namespace std;
 5 typedef long long LL;
 6 const int M=300100,N=1010;
 7 int a,b,c,d,k,n,m,x[N];LL bin[40];
 8 struct Trie
 9 {
10     int size;Trie *ch[2]; 
11     Trie(){size=0;ch[0]=ch[1]=NULL;}
12 }*null=new Trie(),*root[M];
13 vector<Trie*>v[5];
14 vector<int>vec;
15 inline Trie* newTrie(){Trie *o=new Trie();o->ch[0]=o->ch[1]=null;return o;}
16 void insert(Trie *&o,Trie *old,int val,int i)
17 {
18     if(i<0)return;
19     int d=((val&bin[i])==bin[i]);
20     o->ch[d]=newTrie();o->ch[d^1]=old->ch[d^1];
21     o->ch[d]->size=old->ch[d]->size+1;
22     insert(o->ch[d],old->ch[d],val,i-1);
23 }
24 inline int query()
25 {
26     v[1].clear(),v[2].clear();vec.clear();
27     for(int i=a;i<=b;i++)
28         vec.push_back(x[i]),v[1].push_back(root[c-1]),v[2].push_back(root[d]);
29     int ret=0;
30     for(int i=30;~i;i--)
31     {
32         int tmp=0;
33         for(int j=0,len=v[1].size();j<len;j++)
34         {
35             int d=((vec[j]&bin[i])==bin[i]);
36             tmp+=v[2][j]->ch[d^1]->size-v[1][j]->ch[d^1]->size;
37         }
38         if(tmp>=k)
39         {
40             ret|=bin[i];
41             for(int j=0,len=v[1].size();j<len;j++)
42             {
43                 int d=((vec[j]&bin[i])==bin[i]);
44                 v[1][j]=v[1][j]->ch[d^1],v[2][j]=v[2][j]->ch[d^1];
45             }
46         }
47         else
48         {
49             k-=tmp;
50             for(int j=0,len=v[1].size();j<len;j++)
51             {
52                 int d=((vec[j]&bin[i])==bin[i]);
53                 v[1][j]=v[1][j]->ch[d],v[2][j]=v[2][j]->ch[d];
54             }
55         }
56     }
57     return ret;
58 }
59 int main()
60 {
61     int q;scanf("%d%d",&n,&m);
62     bin[0]=1;for(int i=1;i<=35;i++)bin[i]=bin[i-1]<<1;
63     root[0]=newTrie();null->ch[0]=null->ch[1]=null;
64     for(int i=1;i<=n;i++)scanf("%d",&x[i]);
65     for(int i=1;i<=m;i++)
66         root[i]=newTrie(),scanf("%d",&a),insert(root[i],root[i-1],a,30);
67     scanf("%d",&q);
68     while(q--)
69         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k),printf("%d\n",query());
70 }

 

posted @ 2017-08-03 21:23  LadyLex  阅读(309)  评论(0编辑  收藏  举报