标签:ati 问题 题目 i++ src seconds value with fine
题目大意:给出n个数字,m次区间询问,每一次区间询问都是询问 l 到 r 之间出现次数为偶数的数 的亦或和。
思路:偶数个相同数字亦或得到0,奇数个亦或得到本身,那么如果把一段区间暴力亦或,得到的其实就是出现次数为奇数的数字的亦或和,所以我们希望这段区间内的所有数字出现次数都+1,使奇偶性互换。
我们先处理出前缀的亦或和,这样可以得到次数为奇数的亦或和。
接下来的问题就是要改变一段区间的奇偶性了,也就是说,这个问题其实就转化成了如何求一段区间出现的所有数字(无重复)。
这里我学到的是用树状数组离线处理的方式。核心代码如下。
for(int i=1;i<=m;i++){ while(p<=ask[i].r) { if(pos[a[p]]==0)//对于每一个第一次出现的数字,加入树状数组,并且记录。 { pos[a[p]]=p; update(p,a[p]); }else { update(pos[a[p]],a[p]);//如果曾经出现过,则将之前的位置清空,更新树状数组和记录。 update(p,a[p]); pos[a[p]]=p; } p++; } ask[i].ans=pre[ask[i].r]^pre[ask[i].l-1]^getxor(ask[i].r)^getxor(ask[i].l-1); }
如此操作后,比如我们询问的是1- R 的区间,此时肯定能得到我要的东西,但是如果我们询问的是1- r 这个区间的话(r<R),这个信息可能就不对了!!但是精彩的地方来了,由于我们事先对询问的区间排过序,也就是说,如果是纯粹的询问1-r区间,这个操作肯定在询问1-R之前,所以不会有影响,而如果我们计算的是r-R这个区间,此时1-r这个东西是出现在 减数 的位置的,也就是说,如果有一个数字在1-r和r-R中间都出现过,则此时1-r的树状数组为0,而1-R的树状数组为1!!
所以根据这个思路把他转化成亦或的求法就可以了。
接下来上代码。
#include<cstdio> #include<cstring> #include<stdlib.h> #include<algorithm> #include<iostream> #include<map> #define CLR(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int maxn=1000010; ll pre[maxn],tree[maxn<<2],a[maxn]; int n,m; struct node{ int l,r,id; ll ans; }ask[maxn]; bool cmp(const node a,const node b) { return a.r<b.r; } bool cmpid(const node a,const node b) { return a.id<b.id; } inline int lowbit(int k){ return (-k)&k; } inline void update(int x,ll val){ while(x<=n){ tree[x]^=val; x+=lowbit(x); } } inline ll getxor(int x){ ll ans=0; while(x>0){ ans^=tree[x]; x-=lowbit(x); } return ans; } map<ll,int >pos; int main(){ cin>>n; scanf("%lld",&a[1]); pre[1]=a[1]; for(int i=2;i<=n;i++) { scanf("%lld",&a[i]); pre[i]=pre[i-1]^a[i]; } cin>>m; for(int i=1;i<=m;i++) { scanf("%d%d",&ask[i].l,&ask[i].r); ask[i].id=i; } sort(ask+1,ask+1+m,cmp); int p=1; for(int i=1;i<=m;i++){ while(p<=ask[i].r) { if(pos[a[p]]==0) { pos[a[p]]=p; update(p,a[p]); }else { update(pos[a[p]],a[p]); update(p,a[p]); pos[a[p]]=p; } p++; } ask[i].ans=pre[ask[i].r]^pre[ask[i].l-1]^getxor(ask[i].r)^getxor(ask[i].l-1); } sort(ask+1,ask+1+m,cmpid); for(int i=1;i<=m;i++) { printf("%lld\n",ask[i].ans); } }
Little Mishka enjoys programming. Since her birthday has just passed, her friends decided to present her with array of non-negative integers a1,?a2,?...,?an of n elements!
Mishka loved the array and she instantly decided to determine its beauty value, but she is too little and can‘t process large arrays. Right because of that she invited you to visit her and asked you to process m queries.
Each query is processed in the following way:
Since only the little bears know the definition of array beauty, all you are to do is to answer each of queries presented.
The first line of the input contains single integer n (1?≤?n?≤?1?000?000) — the number of elements in the array.
The second line of the input contains n integers a1,?a2,?...,?an (1?≤?ai?≤?109) — array elements.
The third line of the input contains single integer m (1?≤?m?≤?1?000?000) — the number of queries.
Each of the next m lines describes corresponding query by a pair of integers l and r (1?≤?l?≤?r?≤?n) — the bounds of query segment.
Print m non-negative integers — the answers for the queries in the order they appear in the input.
3
3 7 8
1
1 3
0
7
1 2 1 3 3 2 3
5
4 7
4 5
1 3
1 7
1 5
0
3
1
3
2
In the second sample:
There is no integers in the segment of the first query, presented even number of times in the segment — the answer is 0.
In the second query there is only integer 3 is presented even number of times — the answer is 3.
In the third query only integer 1 is written down — the answer is 1.
In the fourth query all array elements are considered. Only 1 and 2 are presented there even number of times. The answer is .
In the fifth query 1 and 3 are written down. The answer is .
codeforces 703D Mishka and Interesting sum 偶数亦或 离线+前缀树状数组
标签:ati 问题 题目 i++ src seconds value with fine
原文地址:https://www.cnblogs.com/mountaink/p/9794900.html