atcoder ARC092 D - Two Sequences 二分 & 二進制
今天生日捏,嘻嘻~
題意:給定A B數組長度為n 求所有 (1<=i,j <=n ) a[i]+b[j] 的異或和。 n <=200000 ai bi <=228
這題比賽沒寫出來,而且完全沒思路,結束後看了zz大佬的博客大致有了解題方向,然後再參考了cyc的...於是大致會寫了。
由於xor 實際上是每一位的xor ,所以考慮一位一位的算出答案。(即算出答案在二進制下的每一位的數字 0 或 1)
ps:以下的每一個數都為二進制,位數從右往左數。
可以證明,已知 某一位上有 x 個 1 y 個0 的話, 這一位上xor後為 x mod 2。
這樣就將問題轉換為: 求所有 a[i]+b[j] 在二進制下,每一位分別的 1 的個數 之和。
舉個栗子!
如樣例
001 010
011 100
a[i]+b[j]分別為:
100
101
101
110
第1位有0 1 1 0 共2個 1 mod 2後為 0 (從左往右的第3位)
第2位有0 0 0 1 共1個 1 mod 2後為 1 (從左往右的第2位)
第3位有1 1 1 1 共4個 1 mod 2後為 0 (從左往右的第1位)
於是答案就是 (010)2=(2)10
然後就可以開始一位位的考慮了
當我們計算答案的第 k 位時,發現 a[i] b[j] 的k+1位之後的 (如當k=2 ,a[i]=100,那麽k+1為之後的即 1)
對第k位的答案是沒有作用的,因為當a[i]+b[j]後,k+1位之後的數對k沒有任何影響。
所以就可以將k+1之後的都給扔掉。
於是我萌設
c[i]=a[i] and ((1 << k)-1)
d[i]=b[i] and ((1 << k)-1)
and ((1 << k)-1) 就相當於可以把k位都拿出來了
如 一個數10101110 k=4 那麽
10101110 and
00001111
=00001110
至於為什麽可以就自己思考一下。
由於0的個數是沒有用的,所以考慮1就好了
發現0<=c[i],d[j]< 2k
對於第k位可以有一個 1
只有滿足
①2k-1<=c[i]+d[j]<2k 這個就相當於
c[i]+d[j]沒有向下一位進 1 而且第 k 位會是 1 因為 2k-1
這樣的一個範圍裏就包含了所有第k位是1的所以數 ,而c[i]+d[j] 在這個範圍裏 所以說明對第 k 位有一個1 的貢獻。
或
②2k+2k-1<=c[i]+d[j]<2k+1
類比第一個,這個就是對下一位進1 後的且第k為是1。
一樣可以得到這樣的一個範圍能滿足 第k+1位是1 且 第k位是1。
那到底有多少個c[i]+d[j] 是在以上的兩個範圍的其中一個
只要求出有多少個這樣的數對 (i,j) 滿足 c[i]+d[j] 是以上兩個範圍裏的其中一個,問題就解決了(求出了有多少個1了)
考慮固定 j 移動 i
把c數組從小到大排序。
只要找到最左的 i (L)和最右的 i(R) 這樣由於單調性 L~R 中的 i 都是滿足條件的,所以 R-L+1即是1的個數。
所以分兩類 分別計算出兩類的個數加起來即可
而對於L R 用二分就好了。
這題是我接觸的比較新的題,寫詳細些,自己因為二分一個小地方敲錯了一直tle,以後要註意。
最後的話,生日快樂!
1 var n:longint; 2 i,k:longint; 3 a,b,c,d,heap:array[0..201000]of int64; 4 m0,m1:int64; 5 ans,tot,x,y:int64; 6 procedure swap(var a,b:int64); 7 var t:longint; 8 begin 9 t:=a;a:=b;b:=t; 10 end; 11 procedure up(x:longint); 12 begin 13 while x>1 do 14 begin 15 if heap[x]<heap[x div 2] then 16 begin 17 swap(heap[x],heap[x div 2]); 18 x:=x div 2; 19 end else break; 20 end; 21 end; 22 procedure down(x:longint); 23 var min:longint; 24 begin 25 while x*2<=tot do 26 begin 27 min:=x*2; 28 if (x*2+1<=tot)and(heap[x*2+1]<heap[min]) then inc(min); 29 if heap[x]>heap[min] then 30 begin 31 swap(heap[x],heap[min]); 32 x:=min; 33 end else break; 34 end; 35 end; 36 37 procedure sort; 38 var i,j:longint; 39 begin 40 for i:=1 to n do 41 begin 42 c[i]:=heap[1]; 43 heap[1]:=heap[tot]; 44 dec(tot); 45 down(1); 46 end; 47 end; 48 function find(x:int64):longint; 49 var l,r,m:longint; 50 begin 51 l:=1; 52 r:=n; 53 while l<=r do 54 begin 55 m:=(l+r)>>1; 56 if c[m]<x then l:=m+1 else r:=m-1; 57 end; 58 exit(l); 59 end; 60 61 begin 62 read(n); 63 for i:=1 to n do 64 read(a[i]); 65 for i:=1 to n do 66 read(b[i]); 67 c[0]:=-1; 68 c[n+1]:=1 << 45; 69 for k:=1 to 29 do 70 begin 71 tot:=0; 72 x:=1 << k; 73 y:=1 << (k-1); 74 for i:=1 to n do 75 begin 76 heap[i]:=a[i] and (x-1); 77 inc(tot); 78 up(i); 79 d[i]:=b[i] and (x-1); 80 end; 81 //writeln(k); 82 sort; 83 m0:=0; 84 m1:=0; 85 for i:=1 to n do 86 begin 87 m1:=m1+find(x-d[i])-find(y-d[i]); 88 m1:=m1+n+1-find(x+y-d[i]); 89 //inc(m1); 90 end; 91 //writeln(‘0=‘,m0,‘ 1=‘,m1); 92 if m1 and 1 =1 then ans:=ans+y; 93 end; 94 writeln(ans); 95 end.ARC072D
atcoder ARC092 D - Two Sequences 二分 & 二進制