CF #365 703D. Mishka and Interesting sum
题目描述
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的更多相关文章
- Codeforces 703D Mishka and Interesting sum 离线+树状数组
链接 Codeforces 703D Mishka and Interesting sum 题意 求区间内数字出现次数为偶数的数的异或和 思路 区间内直接异或的话得到的是出现次数为奇数的异或和,要得到 ...
- codeforces 703D Mishka and Interesting sum 偶数亦或 离线+前缀树状数组
题目传送门 题目大意:给出n个数字,m次区间询问,每一次区间询问都是询问 l 到 r 之间出现次数为偶数的数 的亦或和. 思路:偶数个相同数字亦或得到0,奇数个亦或得到本身,那么如果把一段区间暴力亦或 ...
- Codeforces 703D Mishka and Interesting sum(离线 + 树状数组)
题目链接 Mishka and Interesting sum 题意 给定一个数列和$q$个询问,每次询问区间$[l, r]$中出现次数为偶数的所有数的异或和. 设区间$[l, r]$的异或和为$ ...
- Codeforces 703D Mishka and Interesting sum(树状数组+扫描线)
[题目链接] http://codeforces.com/contest/703/problem/D [题目大意] 给出一个数列以及m个询问,每个询问要求求出[L,R]区间内出现次数为偶数的数的异或和 ...
- CodeForces 703D Mishka and Interesting sum
异或运算性质,离线操作,区间求异或和. 直接求区间出现偶数次数的异或和并不好算,需要计算反面. 首先,很容易求解区间异或和,记为$P$. 例如下面这个序列,$P = A[1]xorA[2]xorA[3 ...
- CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组
题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有 ...
- CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)
转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interestin ...
- CF #365 DIV2 D Mishka and Interesting sum 区间异或+线段树
D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes in ...
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 离线+线段树
题目链接: http://codeforces.com/contest/703/problem/D D. Mishka and Interesting sum time limit per test ...
随机推荐
- 配置Server Side TAF
实验环境:Oracle 11.2.0.4 RAC 参考MOS文档: How To Configure Server Side Transparent Application Failover (文档 ...
- React组件开发(一)初识React
*React不属于MVC.MVVM,只是单纯的V层. *React核心是组件(提高代码复用率.降低测试难度.代码复杂度). *自动dom操作,状态对应内容. *React核心js文件:react.js ...
- Rotate Array leetcode
Rotate an array of n elements to the right by k steps. For example, with n = 7 and k = 3, the array ...
- Django HTTP处理流程(自我总结)
Django中由wsgi模块接管http请求,核心处理方法为get_wsgi_application,其定义如下: def get_wsgi_application(): ""&q ...
- Spring Data JPA 实例查询
一.相关接口方法 在继承JpaRepository接口后,自动拥有了按"实例"进行查询的诸多方法.这些方法主要在两个接口中定义,一是QueryByExampleExecut ...
- (28)初识struts框架
案例剖析中介绍了一个自己写的mystruts框架,这里开始简单的认识struts框架. 1.先看一个简单的struts开发的例子来熟悉一下流程 Struts就是基于mvc模式的框架! (struts其 ...
- oracle数据库如何打印九九乘法表
对于九九乘法表,相信对于懂IT的人并不陌生,但是外行可能会有很多的不懂,c语言也同样需要了解,它是学习的入门课程,oracle数据库书写九九乘法表有好几种方式,下面就有我为大家介绍,一起来看看吧. 九 ...
- CSS -- 练习之制作简单商品图
只加深了印象,出错点:未给左侧人物大图宽高,致使第二行图层叠在其上: <!DOCTYPE html> <html lang="en"> <head&g ...
- 使用moment.js轻松管理日期和时间
大家在前端Javascript开发中会遇到处理日期时间的问题,经常会拿来一大堆处理函数才能完成一个简单的日期时间显示效果.今天我给大家介绍一个轻量级的Javascript日期处理类库:moment.j ...
- Android Doze模式启用和恢复
从Android 6.0(API level 23)开始,Android提出了两个延长电池使用时间的省电特性给用户.用户管理可以在没有充电的情况下管理app的行为.当用户一段时间没有使用手机的时候,D ...