码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-03-18 16:23:39      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:就是   alt   href   swa   图片   img   tco   条件   pos   

今天生日捏,嘻嘻~

题意:给定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]<2这个就相当于   

    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 二分 & 二进制

标签:就是   alt   href   swa   图片   img   tco   条件   pos   

原文地址:https://www.cnblogs.com/Bunnycxk/p/8595424.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!