[ARC092D] Two Sequences
Time Limit: 3 sec / Memory Limit: 256 MB
难度:\(4.0\)
- 
Problem Statement
You are given two integer sequences, each of length \(N\): \(a_1, \cdots ,a_N\) and \(b_1, \cdots ,b_N\).
There are \(N^2\) ways to choose two integers \(i\) and \(j\) such that \(1 \leq i,j \leq N\). For each of these \(N^2\) pairs, we will compute \(a_i+b_j\) and write it on a sheet of paper. That is, we will write \(N^2\) integers in total.
Compute the XOR of these \(N^2\) integers.
给定两个长度为 \(n\) 的正整数数组 \(a,b\) ,求 \(\forall 1 \leq i,j \leq n\),\(a_i+b_j\) 在二进制下的异或和 。
- 
Input
\(n\) 和两数组 \(a,b\) 。
- 
Output
答案。
- 
Sample Input
| 1 2 3 | 5 1 2 3 4 5 1 2 3 4 5 | 
- 
Sample Output
| 1 | 2 | 
- 
Constraints
\(1 \leq n \leq 200000\),\(1 \leq a_i,b_j \leq 2^{28}\)。
Source:ARC092D
from orz zzx:
对每一位 \(d\),求有多少对 \(i,j\) 满足 \(a_i+b_j\) 的第 \(d\) 位为 \(1\),也就是 \((a_i+b_j) \bmod 2d+1 \geq 2d\),单调性扫一扫就行了,复杂度 \(O(n(\log a_i+\log b_i))\)。
这题比我在泉州集训出的某个题略微简单一点,那个题是求所有 \(l \leq r\)
的 \(\sum\limits_{i=l}^r a_i\) 的异或和,思路类似。
from sb mnihyc:
「单调性扫一扫」想得不是很清楚的可以直接排序+二分。
具体来说就是:枚举位,要查找序列中有多少个数当前位为 \(1\)。
如果要查找 \(N\) 次的话,普通查找的复杂度就是 \(N^2\)。
显然我们可以通过排序优化这个操作。
将其中一个数组排序后再查找,目标就变成了有序序列中连续的单调的一段,使用二分,复杂度 \(O(n \log n)\)。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |     #include <cstdio>     #include <cstdlib>     #include <cstring>     #include <climits>     #include <algorithm>     #define _max(_a_,_b_) ((_a_)>(_b_)?(_a_):(_b_))     #ifdef ONLINE_JUDGE         char __B[1<<15],*__S=__B,*__T=__B;         #define getchar() (__S==__T&&(__T=(__S=__B)+fread(__B,1,1<<15,stdin),__S==__T)?EOF:*__S++)     #endif     inline int getnum()     {         register char c=0;         while(!(c>='0' && c<='9'))             c=getchar();         register int a=0;         while(c>='0' && c<='9')             a=a*10+c-'0',c=getchar();         return a;     }     int a[205050],b[205050];     #define GetLen(_arr,_l,_r) (std::lower_bound(&(_arr)[1],&(_arr)[N+1],_r)-std::lower_bound(&(_arr)[1],&(_arr)[N+1],_l))     int ta[205050],tb[205050];     int main()     {         register int N=getnum(),mxv=0;         for(register int i=1;i<=N;i++)             a[i]=getnum(),mxv=_max(mxv,a[i]);         for(register int i=1;i<=N;i++)             b[i]=getnum(),mxv=_max(mxv,b[i]);         register unsigned dig=1;         while(mxv)             dig++,mxv>>=1;         int ans=0,pw2=1;         while(dig--)         {             for(register int i=1;i<=N;i++)                 ta[i]=a[i]&((pw2<<1)-1),tb[i]=b[i]&((pw2<<1)-1);             std::sort(&tb[1],&tb[N+1]);             register bool sum=0;             for(register int i=1;i<=N;i++)                 sum^=GetLen(tb,pw2-ta[i],(pw2<<1)-ta[i])&1,                 sum^=GetLen(tb,pw2+(pw2<<1)-ta[i],(pw2<<2)-ta[i])&1;             ans|=pw2*sum,pw2<<=1;         }         printf("%d\n",ans);         return 0;     } |