比赛-ZR DAY1 (4, Aug)

Posted ghcred

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比赛-ZR DAY1 (4, Aug)相关的知识,希望对你有一定的参考价值。

A. 数对子

题目可以转化为,在一些区间的并集中,计算二进制中 1 的数量为奇数的数的个数 s0,以及 1 的数量为偶数的数的个数 s1,答案就是 s0*s1 。因为异或之后 1 的数量为奇数,说明异或前两数奇偶性相异。考虑处理 [0, i] 区间中,1 的数量为奇数的数的个数,写一个 cal1(i) 来计算。

分析发现 (0, 1), (2, 3), (4, 5) ... 这些数对,二进制下的 1 的个数总是相差 1 ,因为个位相差 1. 故 cal1(5) = 3 ,因为 (0, 1), (2, 3), (4, 5) 这三对数里,每一对都可有一个 1 的个数是奇数的数。推理可得:cal1(奇数 n) = (n + 1) / 2 ,cal1(偶数 n) = n / 2 + (pop_count(n) & 1) 。这之后维护一个线段树处理并集就行了。

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 
 8 const ll MX = (1ll<<32)-1;
 9 const ll _N = 5000000;
10 
11 int STCnt = 1, rt = 1, L[_N], R[_N], Lazy[_N];
12 ll S1[_N], S0[_N];
13 
14 ll cal1(ll n)
15 {
16     if (n&1) return (n+1)/2;
17     return n/2+(__builtin_popcount(n)&1);
18 }
19 
20 void MDF(int &p, ll l, ll r, ll s, ll t)
21 {
22     if (!p) p = ++STCnt;
23     if (s <= l && r <= t) { S1[p] = cal1(r)-cal1(l-1), S0[p] = r-l+1-S1[p], Lazy[p] = 1; return; }
24     if (Lazy[p]) return;
25     if (!L[p]) L[p] = ++STCnt;
26     if (!R[p]) R[p] = ++STCnt;
27     ll mid = (l+r)>>1;
28     if (s <= mid && t >= l) MDF(L[p], l, mid, s, t);
29     if (s <= r && t > mid) MDF(R[p], mid+1, r, s, t);
30     S0[p] = S0[L[p]]+S0[R[p]];
31     S1[p] = S1[L[p]]+S1[R[p]];
32     return;
33 }
34 
35 int main()
36 {
37     int N;
38     scanf("%d", &N);
39     while (N--) {
40         ll l, r;
41         scanf("%lld%lld", &l, &r);
42         MDF(rt, 1, MX, l, r);
43         printf("%lld
", S1[rt]*S0[rt]);
44     }
45     return 0;
46 }

 

以上是关于比赛-ZR DAY1 (4, Aug)的主要内容,如果未能解决你的问题,请参考以下文章

zr-csp 7联测 day1

zr 10联测 day1

正睿2018暑假集训 比赛题选做

比赛-训练赛 (15 Aug, 2018)

比赛-模拟赛 (Aug 18, 2018)

比赛-CioCio的训练赛 (Aug 18, 2018)