CF #365 703D. Mishka and Interesting sum

时间:2022-08-27 23:09:04

题目描述

D. Mishka and Interesting sum的意思就是给出一个数组,以及若干询问,每次询问某个区间[L, R]之间所有出现过偶数次的数字的异或和。

这个东西乍看很像是经典问题,一列数字中所有数字出现偶数次,除了一个数字只出现一次,找出那个只出现过一次的数字。然而这个问题并不是要找出现奇数次数字的异或和。

算法

有一个直观的思路是求出[L, R的异或和,再异或上[L, R]之间所有出现过的数字的异或和。这样的话就可以使得数字出现次数的奇偶性发生变化。

那么怎么求出区间[L, R]所有出现过的数字的异或和呢?

先想一下如果是求区间[L, R]有多少种不同的数字怎么做?这个可以在遍历的时候保存每个数字最后出现的位置,打标记(去掉上一次的标记,更新到当前位置),去数[L, R]有多少个标记就行了。

所以求[L, R]不同数字的异或和也是类似的做法,去掉之前出现位置的标记,给当前位置打上标记,去计算[L,R]所有标记异或和。

回到原问题,有了区间不同数字的异或和,再异或上区间本身的异或值,就可以实现奇偶性翻转来得出出现偶数次的数字的异或和。

具体的流程:

需要一个异或BIT/FenwickTree,以及一个hashmap来保存元素出现位置。

按照所有询问的right值排序,遍历所有数字,每一次遍历到当前要处理的询问的R值为止。

每一步都要先往BIT中i位置加一个a[i](要做区间本身数字的异或)。

如果当前数字是第一次出现,则向BIT中i位置加一个a[i],hashmap中标记a[i]出现的位置为i。

如果当前数字之前已经出现过了,先去除上一次的标记,即向BIT中last[a[i]]加一个a[i](对于异或来说就抵消了),再向当前位置i加入一个a[i],更新hashmap中a[i]的位置为i。

可以发现,无论数字是否是第一次出现,最终hashmap中都得要给i这个位置加一个a[i],和上述每一个位置都要插入a[i]正好就抵消效果了。

所以流程可以简化为:每一步判断hashmap中是否存在a[i],存在的话取出位置值,BIT中往这个位置加a[i]。 在hashmap中插入<a[i], i>。

每一个询问的答案就是bit.query(R)^bit.query(L-1)

实现

public class Main {
public static void main(String[] args) {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
InputReader in = new InputReader(inputStream);
PrintWriter out = new PrintWriter(outputStream);
TaskD solver = new TaskD();
solver.solve(1, in, out);
out.close();
} static class TaskD {
public void solve(int testNumber, InputReader in, PrintWriter out) {
int n = in.nextInt();
long[] a = new long[n + 1];
for (int i = 1; i <= n; i++) {
a[i] = in.nextLong();
}
int m = in.nextInt();
Query[] queries = new Query[m];
for (int i = 0; i < m; i++) {
queries[i] = new Query(i, in.nextInt(), in.nextInt());
}
Arrays.sort(queries, (o1, o2) -> Integer.compare(o1.right, o2.right));
Map<Long, Integer> pos = new HashMap<>();
FenwickTree tree = new FenwickTree(n) {
@Override
protected long operate(long data, long value) {
return data ^ value;
}
@Override
public long sum(int s, int t) {
return sum(t) ^ sum(s - 1);
}
};
int i = 1;
long[] result = new long[m];
for (Query query : queries) {
for (; i <= query.right; i++) {
if (pos.containsKey(a[i])) {
tree.add(pos.get(a[i]), a[i]);
}
pos.put(a[i], i);
}
result[query.id] = tree.sum(query.left, query.right);
}
for (long ret : result) {
out.println(ret);
}
} class Query {
int id;
int left;
int right; public Query(int id, int left, int right) {
this.id = id;
this.left = left;
this.right = right;
} } } static class InputReader {
private final BufferedReader reader;
private StringTokenizer tokenizer; public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream));
tokenizer = null;
} public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
} public int nextInt() {
return Integer.parseInt(next());
} public long nextLong() {
return Long.parseLong(next());
} } static class FenwickTree {
private final long[] data; public FenwickTree(int size) {
data = new long[size + 1];
} public FenwickTree(long[] data) {
this.data = data;
} private int lowBit(int x) {
return x & -x;
} protected long operate(long data, long value) {
return data + value;
} public final void add(int p, long v) {
for (int i = p; i < data.length; i += lowBit(i)) {
data[i] = operate(data[i], v);
}
} public final long sum(int p) {
long ret = 0;
for (int i = p; i > 0; i -= lowBit(i)) {
ret = operate(ret, data[i]);
}
return ret;
} public long sum(int s, int t) {
return sum(t) - sum(s - 1);
} }
}

CF #365 703D. Mishka and Interesting sum的更多相关文章

  1. Codeforces 703D Mishka and Interesting sum 离线&plus;树状数组

    链接 Codeforces 703D Mishka and Interesting sum 题意 求区间内数字出现次数为偶数的数的异或和 思路 区间内直接异或的话得到的是出现次数为奇数的异或和,要得到 ...

  2. codeforces 703D Mishka and Interesting sum 偶数亦或 离线&plus;前缀树状数组

    题目传送门 题目大意:给出n个数字,m次区间询问,每一次区间询问都是询问 l 到 r 之间出现次数为偶数的数 的亦或和. 思路:偶数个相同数字亦或得到0,奇数个亦或得到本身,那么如果把一段区间暴力亦或 ...

  3. Codeforces 703D Mishka and Interesting sum(离线 &plus; 树状数组)

    题目链接  Mishka and Interesting sum 题意  给定一个数列和$q$个询问,每次询问区间$[l, r]$中出现次数为偶数的所有数的异或和. 设区间$[l, r]$的异或和为$ ...

  4. Codeforces 703D Mishka and Interesting sum(树状数组&plus;扫描线)

    [题目链接] http://codeforces.com/contest/703/problem/D [题目大意] 给出一个数列以及m个询问,每个询问要求求出[L,R]区间内出现次数为偶数的数的异或和 ...

  5. CodeForces 703D Mishka and Interesting sum

    异或运算性质,离线操作,区间求异或和. 直接求区间出现偶数次数的异或和并不好算,需要计算反面. 首先,很容易求解区间异或和,记为$P$. 例如下面这个序列,$P = A[1]xorA[2]xorA[3 ...

  6. CF &num;365 &lpar;Div&period; 2&rpar; D - Mishka and Interesting sum 离线树状数组

    题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有 ...

  7. CF &num;365 &lpar;Div&period; 2&rpar; D - Mishka and Interesting sum 离线树状数组(转)

    转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interestin ...

  8. CF &num;365 DIV2 D Mishka and Interesting sum 区间异或&plus;线段树

    D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes in ...

  9. Codeforces Round &num;365 &lpar;Div&period; 2&rpar; D&period; Mishka and Interesting sum 离线&plus;线段树

    题目链接: http://codeforces.com/contest/703/problem/D D. Mishka and Interesting sum time limit per test ...

随机推荐

  1. iOS中—触摸事件详解及使用

    iOS中--触摸事件详解及使用 (一)初识 要想学好触摸事件,这第一部分的基础理论是必须要学会的,希望大家可以耐心看完. 1.基本概念: 触摸事件 是iOS事件中的一种事件类型,在iOS中按照事件划分 ...

  2. MSSQL - 存储过程OutPut返回值

    1.存储过程中不使用外部参数. 存储过程: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ========================== ...

  3. Android系统服务详解-android学习之旅(95)

    本文是看完android框架揭秘第六章后的总结 android系统服务提供最基本的,最稳定的核心功能,如设备控制,信息通知,通知设定,以及消息显示等,存在于Android Framework与Andr ...

  4. Linux内核参数调优

    用法: vim /etc/sysctl.conf #修改内容 sysctl -p #生效 相关参数仅供参考,具体数值还需要根据机器性能,应用场景等实际情况来做更细微调整.   net.core.net ...

  5. &lbrack;HNOI2012&rsqb;集合选数(状压DP&plus;构造)

    题目要求若出现x,则不能出现2x,3x 所以我们考虑构造一个矩阵 \(1\ 2\ 4 \ 8--\) \(3\ 6\ 12\ 24--\) \(9\ 18\ 36--\) \(--\) 不难发现,对于 ...

  6. Contest2178 - 2019-4-18 高一noip基础知识点 测试7 题解版

    刚刚改完题,才有时间发题解 传送门 T1 exgcd裸题 对a,b跑exgcd,答案就是x*c/gcd(a,b),y*c/gcd(a,b) 不合法的情况:当且仅当c%gcd(a,b)!=0 代码 T2 ...

  7. sql判断字段是否为空

    sql语句条件查询时,有时会判断某个字段是否为空. 字段内容为空有两种情况 1.为null 2.为字符串的空'' 语句如下: select * from table where column is n ...

  8. P2055 &lbrack;ZJOI2009&rsqb;假期的宿舍

    思路 看到复杂的匹配条件,发现要让一个人和一个床匹配,所以就每个有床的人(指本校学生)和t连一条边,每个需要床的人(指外校的人和不回家的人)和s连一条边,i和j互相认识就把i和j的床连在一起,自己和自 ...

  9. javascript学习笔记(五):异常捕获和事件处理

    异常捕获 Try{ 发生异常的代码块 }catch(err){ 异常信息处理 } <!DOCTYPE html> <html> <head lang="en&q ...

  10. 解题:USACO07FEB The Cow Lexicon

    题面 第一次做Trie上dp,感谢 @i207M 的资瓷 对子串们建立一棵Trie,设$dp[i][j]$表示到母串第$i$位为止在$Trie$上的$j$号节点时的最小修改数量,然后就可以枚举母串各位 ...