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

比赛-ZR DAY1 (4, Aug)

时间:2018-08-04 18:58:49      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:clu   mes   并集   集中   奇数   \n   main   day   一个   

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\n", S1[rt]*S0[rt]);
44     }
45     return 0;
46 }

 

比赛-ZR DAY1 (4, Aug)

标签:clu   mes   并集   集中   奇数   \n   main   day   一个   

原文地址:https://www.cnblogs.com/ghcred/p/9419315.html

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