Mail.Ru Cup 2018 Round 1D. Shurikens(思维 + 贪心)

66 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路
\

题目

At a break Vanya came to the class and saw an array of nn kk-bit integers a1,a2,,ana_1, a_2, \ldots, a_n on the board. An integer xx is called a kk-bit integer if 0x2k10 \leq x \leq 2^k - 1. Of course, Vanya was not able to resist and started changing the numbers written on the board. To ensure that no one will note anything, Vanya allowed himself to make only one type of changes: choose an index of the array ii (1in1 \leq i \leq n) and replace the number aia_i with the number ai\overline{a_i}. We define x\overline{x} for a kk-bit integer xx as the kk-bit integer such that all its kk bits differ from the corresponding bits of xx. Vanya does not like the number 00. Therefore, he likes such segments [l,r][l, r] (1lrn1 \leq l \leq r \leq n) such that alal+1ar0a_l \oplus a_{l+1} \oplus \ldots \oplus a_r \neq 0, where \oplus denotes the bitwise XOR operation. Determine the maximum number of segments he likes Vanya can get applying zero or more operations described above.

中文大意

给我们一个数字nn和一个数字knk,n表示数组中的元素个数k表示每个aia_i的二进制位数不超过kk我们可以任意对元素操作让aia_i二进制k位上的数都不同问有多少区间alal+1ar0a_l \oplus a_{l+1} \oplus \ldots \oplus a_r \neq 0

解法

根据鸽巢原理我们可以知道如果再一段连续的区间异或和中出现了两个相同的值那么就可以确定在这两点之间的区间的异或和是为0的所以本题跟着这个思路来写。
然后我们利用贪心思想从左往右每次让这个区间中连续异或和不为0的数量最大即可

int a[N];
void solve()
{
   int n,k; cin >> n >> k;
   k = 1 << k;
   k -= 1;
   rep(i,n) cin >> a[i];
   map<int,int> mp;
   mp[0] = 1;
   int res = 0;
   for(int i = 1; i <= n; i++) {
       a[i] ^= a[i-1];
       if(mp[a[i]] >= mp[a[i] ^ k]) a[i] ^= k;
       res += mp[a[i]] ++;
   }
   cout << n * (n + 1) / 2 - res << endl;
}