题目描述

初始给定n个卡片拍成一排,其中第i个卡片上的数为x[i]。

有q个询问,每次询问给定L和R表示询问区间[L,R]内的卡片所有出现了偶数次的数的异或和是多少。

输入

输入文件C.in

输入一行两个整数n,q。

第二行n个整数,第i个数为x[i]。

接下来q行,每行两个整数L和R,表示询问的区间。

输出

输出文件C.out

输出q行,其中第i行表示第i次询问的区间出现偶数次的数的异或和。

样例输入

3 1
3 7 8
1 3

样例输出

0

【样例输入2】

7 5
1 2 1 3 3 2 3
4 7
4 5
1 3
1 7
1 5

【样例输出2】

0
3
1
3
2

【数据范围】

对于20%的数据,$ n , q \le 10^3 $

对于另外20%的数据,$ n , q \le 5 \times 10^4 , a_i \le 10 $

对于100%的数据, $ n , q \le 10^6 , 0 \le a[i] \le 10^9 $

这道毒瘤题.....我->TM->根本->不会

但是我会四十分啊.......

四十分就很简单了,首先,对于前 $ 20 % $ 的数据,直接暴力模拟即可,毫无难度可言

另外 $ 20 % $ 的数据,需要稍微动一点脑子,因为它具有特殊性质:$ a_i \le 10 $

所以可以在前缀和的基础上加一维来作为桶统计出现次数,然后就是判断了,也很简单

虽然写的是40分,但是我得了45分,也算是意外惊喜吧.

四十分代码如下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define max(a,b) (a > b ? a : b)
#define Noip2018RpINF return 0 const int N = 5e4 + 5 ; int n,v[N],q,tra[N],maxi,ans;
int sum_ap[N][15]; inline int read(){
int x = 0 , f = 1 ;char ch = getchar ();
while ( ch < '0' || ch > '9' ){if ( ch == '-' ) f = - 1 ;ch = getchar () ;}
while ( ch >= '0' && ch <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( ch ^ 48 ) ;ch = getchar ();}
return f * x ;
} int main(){
n = read () , q = read() ;
for (int i = 1 ; i <= n ; ++ i) v[i] = read () , maxi = max (maxi , v[i]) ;
if ( n <= 2000 ){
while (q--){
register int l = read () , r = read () ;
memset( tra , false , sizeof (tra) );maxi = - 1 ; ans = 0 ;
for (int i = l ; i <= r ; ++ i) ++ tra[ v [ i ] ] , maxi = max (maxi , v[i]);
for (int i = 1 ; i <= maxi ; ++i){
if( ( tra[i] & 1 ) || ! tra[i] ) continue ;
ans ^= i ;
}
printf("%d\n" , ans);
}
}else if(n <= 50000){
sum_ap[1][v[1]] = 1 ;
for (int i = 2 ; i <= n ; ++ i)
for(int j = 0 ; j <= maxi ; ++ j)
if( v[i] == j ) sum_ap[i][j] = sum_ap[i - 1][j] + 1 ;
else sum_ap[i][j] = sum_ap[i - 1][j] ;
while (q--){
register int l = read () , r = read (); ans = 0 ;
for(int i = 1 ; i <= maxi ;++ i){
if( ! ( (sum_ap[r][i] - sum_ap[ l - 1 ][i]) & 1 ) && (sum_ap[r][i] - sum_ap[ l - 1 ][i]) )
ans ^= i ;
}
printf ("%d\n" , ans);
}
}
Noip2018RpINF;
}

通过我校 $ rjx 大佬 $ 的讲解,我成功学会了这道题的正解:树状数组+前缀异或和

有一点点前置知识: $ a \bigoplus b = c $ 则 $ a = b \bigoplus c $

我们用 $ a $ 表示区间内出现偶数次的数的异或和,用 $ b $ 表示区间内出现了奇数次的数的异或和,用 $ c $ 表示整个区间所有数字的异或和(每个数字只计算一次)

那么,根据上面的性质,我们可以得到如下结论:

$ a = b \bigoplus c $

所以我们就考虑维护区间内出现奇数次的数的异或和以及整个区间所有不同的数字的异或和

区间内出现奇数次的数的异或和显然可以使用前缀异或和来维护

那么整个区间内所有不同的数的异或和呢?

这里我们采用树状数组维护,开一个数组 $ pre_i $ 表示在 $ i $ 这个位置之前的最靠近 $ v_i $ 的数的位置

另一个 $ map $ 表示 $ v_i $ 的下标,用来辅助构建 $ pre $ 数组

然后,我们把所有的询问区间离线,按右端点升序排序,按升序排序的原因是我们从左向右推,这样可以避免推完之后再回去推一遍,从而保证单纯推的过程复杂度保持在 \(\Theta(n)\)

之后,在向右推进的过程中,我们每遇到一个数,如果它没有前缀(即第一次出现,它对应的 $ pre $ 数组为空),那么就直接加入树状数组

否则,现在树状数组中删除它的前缀,再把它加进去,这样,显然我们可以保证最后树状数组中有且仅有每个数字一个,最后我们查询树状数组,再把查询结果异或整段区间的异或和(即出现了奇数次的异或和)就得到该次询问的答案

代码如下:

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <map>
#define lowbit(x) ( - x & x ) using std::map; const int N = 1e6 + 5 ; struct querys{
int left , right , dir ;
}qs[N]; int n,q,v[N],pre[N];
int ans[N],t[N],sum[N];
map < int , int > vis ; inline void update(int dir , int val){
while(dir <= n){
t[dir] ^= val ;
dir += lowbit(dir);
}
return ;
} inline int query(int dir){
register int res = 0 ;
while(dir){
res ^= t[dir] ;
dir -= lowbit(dir);
}
return res;
} inline bool cmp(const querys & a ,const querys & b ){return a.right < b.right ;} int main(){
scanf("%d%d" , & n , & q );
for (int i = 1 ; i <= n ; ++ i){
scanf("%d" , & v[i] );
sum[i] = sum[i - 1] ^ v[i] ;
pre[i] = vis[ v[i] ] ; vis[ v[i] ] = i ;
}
for (int i = 1 ; i <= q ; ++ i)
scanf("%d%d" , & qs[i].left , & qs[i].right ) , qs[i].dir = i ;
std::sort( qs + 1 , qs + q + 1 , cmp );
register int now = 1 ;
for (int i = 1 ; i <= q ; ++ i){
while(now <= qs[i].right){
if( pre[now] ) update( pre[now] , v[now] );
update( now , v[now] ); ++ now ;
}
ans[qs[i].dir] = query( qs[i].right ) ^ query( qs[i].left - 1 ) ^ sum[ qs[i].right ] ^ sum[ qs[i].left - 1 ] ;
}
for (int i = 1 ; i <= q ; ++ i) printf("%d\n" , ans[i]);
return 0;
}

RDay1-Problem 3 C的更多相关文章

  1. 1199 Problem B: 大小关系

    求有限集传递闭包的 Floyd Warshall 算法(矩阵实现) 其实就三重循环.zzuoj 1199 题 链接 http://acm.zzu.edu.cn:8000/problem.php?id= ...

  2. No-args constructor for class X does not exist. Register an InstanceCreator with Gson for this type to fix this problem.

    Gson解析JSON字符串时出现了下面的错误: No-args constructor for class X does not exist. Register an InstanceCreator ...

  3. C - NP-Hard Problem(二分图判定-染色法)

    C - NP-Hard Problem Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:262144 ...

  4. Time Consume Problem

    I joined the NodeJS online Course three weeks ago, but now I'm late about 2 weeks. I pay the codesch ...

  5. Programming Contest Problem Types

        Programming Contest Problem Types Hal Burch conducted an analysis over spring break of 1999 and ...

  6. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  7. BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 4032  Solved: 1817[Submit] ...

  8. [LeetCode] Water and Jug Problem 水罐问题

    You are given two jugs with capacities x and y litres. There is an infinite amount of water supply a ...

  9. [LeetCode] The Skyline Problem 天际线问题

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  10. PHP curl报错“Problem (2) in the Chunked-Encoded data”解决方案

    $s = curl_init(); curl_setopt($s, CURLOPT_POST, true); curl_setopt($s, CURLOPT_POSTFIELDS, $queryStr ...

随机推荐

  1. 循环语句--do...while

    do...while循环 格式: 执行流程 执行顺序:①③④>②③④>②③④…②不满足为止. ①负责完成循环变量初始化. ②负责判断是否满足循环条件,不满足则跳出循环. ③具体执行的语句 ...

  2. H5 俄罗斯方块Demo

    链接:http://pan.baidu.com/s/1hrDM0T2

  3. iview inoput type=textarea 禁止拉伸

    设置 :maxRows.minRows相同即可 <Input v-model="formValidate.remark" type="textarea" ...

  4. jdbc,mybatis,hibernate各自优缺点及区别

    先比较下jdbc编程和hibernate编程各自的优缺点.    JDBC:    我们平时使用jdbc进行编程,大致需要下面几个步骤:    1,使用jdbc编程需要连接数据库,注册驱动和数据库信息 ...

  5. Centos下安装Mysql异常

    问题1: [root@localhost install-files]# rpm -ivh MySQL-server-5.6.27-1.el6.x86_64.rpm --nosignaturePrep ...

  6. php中header函数参数的Cache-control的使用方法

    网页的缓存是由HTTP消息头中的“Cache-control”来控制的,常见的取值有private.no-cache.max-age.must-revalidate等,默认为private.其作用根据 ...

  7. Shell命令-系统信息及显示之stat、du

    文件及内容处理 - stat.du 1. stat:显示inode内容 stat命令的功能说明 stat 命令用于显示 inode 内容.stat 以文字的格式来显示 inode 的内容. stat命 ...

  8. Vuex、axios、跨域请求处理和import/export的注意问题

    一.Vuex 1.介绍 vuex是一个专门为Vue.js设计的集中式状态管理架构. 对于状态,我们把它理解为在data中需要共享给其他组件使用的部分数据. Vuex和单纯的全局对象有以下不同: 1. ...

  9. kubernetes 将pod运行在某些特定的节点上,给节点打标签

    给节点打上标签: kubectl label node  <node_name> GPU=true   #打上标签 GPU=true 在创建pod的yaml文件时:  添加 nodeSel ...

  10. python学习日记(OOP——反射)

    反射 反射就是通过字符串的形式,导入模块:通过字符串的形式,去模块寻找指定函数,并执行.利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动! hasattr ...