首页 > 代码库 > CF703D Mishka and Interesting sum
CF703D Mishka and Interesting sum
题意:给定一个1e6长度的值域1e9的数组。每次给定询问,询问区间内出现偶数次的数的异或和。
题解:首先很显然,每一次询问的答案,等于这个区间所有不同元素异或和异或上区间异或和。(因为出现偶数次的对区间异或和贡献为0,此时剩下的是出现奇数次的数,在取个补集即为答案)
区间异或和前缀和就好了,那问题转化为求区间不同元素异或和。由于这个东西区间合并很困难,所以在线算法是比较不优雅的。那我们考虑离线算法。我们按询问的右端点为第一关键字排序,然后处理到目前这个右端点位置的last数组,last数组定义为每个数最后出现的位置,然后给每个值对应的last附上它的值,这样我们一个区间求异或和可以得到区间不同元素异或和。树状数组一发就好了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 1000000 4 #define LL long long 5 #define lowbit(x) ((x) & -(x)) 6 7 inline LL read() { 8 LL x = 0, f = 1; char a = getchar(); 9 while(a < ‘0‘ || a > ‘9‘) { if(a == ‘-‘) f = -1; a = getchar(); } 10 while(a >= ‘0‘ && a <= ‘9‘) x = x * 10 + a - ‘0‘, a = getchar(); 11 return x * f; 12 } 13 14 int n, a[N + 5], ans[N + 5], sum[N + 5], Q; 15 int fen[N + 5]; 16 map<int, int> last; 17 18 struct query { 19 int id, l, r; 20 bool operator < (const query & w) const { 21 return r < w.r; 22 } 23 } q[N + 5]; 24 25 inline void add(int pos, int val) { if(!pos) return; for(int i = pos; i <= n; i += lowbit(i)) fen[i] ^= val; } 26 27 inline int querysum(int l, int r) { 28 int ret = 0; 29 for(int i = r; i; i -= lowbit(i)) ret ^= fen[i]; 30 for(int i = l - 1; i; i -= lowbit(i)) ret ^= fen[i]; 31 return ret; 32 } 33 34 int main() { 35 n = read(); 36 for(int i = 1; i <= n; i++) a[i] = read(); 37 for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] ^ a[i]; 38 Q = read(); 39 for(int i = 1; i <= Q; i++) q[i].id = i, q[i].l = read(), q[i].r = read(); 40 sort(q + 1, q + 1 + Q); 41 for(int pos = 1, i = 1; i <= Q; i++) { 42 for(; pos <= q[i].r; pos++) { 43 add(last[a[pos]], a[pos]); 44 last[a[pos]] = pos; 45 add(pos, a[pos]); 46 } 47 ans[q[i].id] = querysum(q[i].l, q[i].r) ^ sum[q[i].l-1] ^ sum[q[i].r]; 48 } 49 for(int i = 1; i <= Q; i++) printf("%d\n", ans[i]); 50 return 0; 51 }
CF703D Mishka and Interesting sum
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。