Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)
2017-05-17 17:36
387 查看
http://codeforces.com/contest/703/problem/D
题意:
给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和。
思路:
这儿利用一下异或和的性质,在一个区间中,我们如果把所有数字都异或的话,可以发现最后偶数次的数字异或后都变成了0,只剩下了奇数次的数字异或。
举个例子,{1,2,3,2,3,5}
异或和是1^2^3^2^3^5=1^5
因为最后要计算偶数次数字的异或和,那么最后我们只需要再异或上该区间内所有不同数字即可。
那么我们可以先计算出前缀异或和,之后就只要求区间上的不同数字的异或和即可。
离线树状数组和在线树状数组的不同点是前者是先把所有询问存储下来,排序后再处理。
拿这道题目来说,我们将询问按照右端点从小到大排序,然后依次计算询问,如果当前数字在之前已经出现过,那么就先删去它,然后再插入该数字,这样就保证了这个区间内不同的数字只出现一次,具体可见代码。
题意:
给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和。
思路:
这儿利用一下异或和的性质,在一个区间中,我们如果把所有数字都异或的话,可以发现最后偶数次的数字异或后都变成了0,只剩下了奇数次的数字异或。
举个例子,{1,2,3,2,3,5}
异或和是1^2^3^2^3^5=1^5
因为最后要计算偶数次数字的异或和,那么最后我们只需要再异或上该区间内所有不同数字即可。
那么我们可以先计算出前缀异或和,之后就只要求区间上的不同数字的异或和即可。
离线树状数组和在线树状数组的不同点是前者是先把所有询问存储下来,排序后再处理。
拿这道题目来说,我们将询问按照右端点从小到大排序,然后依次计算询问,如果当前数字在之前已经出现过,那么就先删去它,然后再插入该数字,这样就保证了这个区间内不同的数字只出现一次,具体可见代码。
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<string> #include<vector> #include<queue> #include<cmath> #include<map> using namespace std; typedef long long LL; const int maxn=1e6+5; struct node { int l,r; int id; }q[maxn]; map<int,int> pos; int n,m; int a[maxn]; int c[maxn]; int sum[maxn]; int pre[maxn]; LL ans[maxn]; bool cmp(node a,node b) { return a.r<b.r||(a.r==b.r && a.l<b.l); } int lowbit(int x) { return x&-x; } int XOR_sum(int x) { int ret=0; while(x>0) { ret^=c[x]; x-=lowbit(x); } return ret; } void add(int x,int d) { while(x<=maxn) { c[x]^=d; x+=lowbit(x); } } int main() { //freopen("D:\\input.txt","r",stdin); while(~scanf("%d",&n)) { pos.clear(); sum[0]=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]^a[i]; pre[i]=pos[a[i]]; //记录a[i]这个数前面出现的位置 pos[a[i]]=i; //更新a[i]最晚的出现位置 } scanf("%d",&m); for(int i=0;i<m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q,q+m,cmp); memset(c,0,sizeof(c)); for(int i=0,r=1;i<m;i++) { while(r<=q[i].r) { if(pre[r]) //如果第r个位置的数之前已经出现过,就删去这个数 add(pre[r],a[r]); add(r,a[r]); //添加第r个数 r++; } ans[q[i].id]=XOR_sum(q[i].r)^XOR_sum(q[i].l-1)^sum[q[i].r]^sum[q[i].l-1]; } for(int i=0;i<m;i++) printf("%I64d\n",ans[i]); } return 0; }
相关文章推荐
- Codeforces Round #365 (Div. 2) D Mishka and Interesting sum (离线树状数组)
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)
- 【Codeforces Round 365 (Div 2)D】【离线询问 树状数组 前驱思想】Mishka and Interesting sum 区间内出现次数偶数的数的异或和
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum(离线树状数组)
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum(树状数组)
- Codeforces Round #365 (Div. 2)-D Mishka and Interesting sum(树状数组)
- 【codeforces 703 D】【离线询问 树状数组 前驱思想 前缀异或和】D. Mishka and Interesting sum【 区间内出现次数偶数的数的异或和】
- Codeforces Round #365 (Div. 2) Mishka and Interesting sum 树状数组
- Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum (树状数组维护异或值) ★ ★
- D. Mishka and Interesting sum(树状数组 前缀异或和)
- CodeForces 703D Mishka and Interesting sum (树状数组 区间偶数异或)
- Codeforces 703D Mishka and Interesting sum 树状数组
- codeforces CF703D Mishka and Interesting sum 树状数组
- [CF#365 (Div. 2) Mishka and Interesting sum] 线段树离线处理区间不同数
- 树状数组【CF703D】Mishka and Interesting sum
- CodeForces 703D Mishka and Interesting sum(树状数组 区间异或)
- codeforces 703D Mishka and Interesting sum (树状数组区间异或)
- CodeForces 703D Mishka and Interesting sum (树状数组处理异或和)
- CodeForces703D Mishka and Interesting sum(树状数组)
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 离线+线段树