1. 程式人生 > >atcoder ARC092 D - Two Sequences 二分 & 二進制

atcoder ARC092 D - Two Sequences 二分 & 二進制

IT closed 是我 begin n) -s swa nbsp 固定

今天生日捏,嘻嘻~

題意:給定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 其他都為0 而2k 相當於第k+1位有一個1其他都為0

這樣的一個範圍裏就包含了所有第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 二分 & 二進制