CodeForces 703D Mishka and Interesting sum (树状数组处理异或和)

来源:互联网 发布:我与网络强国演讲稿 编辑:程序博客网 时间:2024/06/15 04:26

题意:求区间上出现偶数次的数 的异或和。


分析: 如果求出现奇数次的数 的异或和,则只需预处理前缀异或和,然后马上就能求出来了。一个数异或偶数次为0。

            所以这题把问题简单化,把偶数次变奇数次,奇数次变偶数次。(主要思想)

           1.预处理前缀异或和(偶数次被异或没了)

           2.pre数组记录当前数上一次出现的位置,没出现过则为0

           3.先把查询记录下来,按右端点排序,方便后面查询,具体看代码。

           4.将元素一个个按位置加进树状数组,如果这个数前面出现过,则在上一次出现的位置异或下这个数,然后再在当前位置加入这个数(相当于把偶数次变奇数次)。

            简单说就是求区间所有数的异或和(去掉重复的)。

          5.这个区间的前缀异或和 异或 区间所有数的异或和(去掉重复的)得到结果。

           这一步是去除区间出现奇数次的数。


第一次在cf用cin cout会T,改用scanf printf  过了 题目给了3.5s    大概用了1.6s



#include<iostream>#include<algorithm>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<vector>#include<cctype>#include<set>#include<map>#include<queue>#include<stack>#include<iomanip>#include<sstream>#include<limits>#define ll long long#define inf 0x3f3f3f3fusing namespace std;const long long INF = 1e18;const int N= 1e6+10;const int maxn = 1e6+10;const int maxm = 2000000001;const int MOD = 1e6;int A[maxn],n;void ADD(int x, int c){     for (int i=x; i<=n; i+=i&(-i)) A[i] ^= c;}int SUM(int x){    int s = 0;    for (int i=x; i>0; i-=i&(-i)) s ^= A[i];    return s;}struct Node{    int l,r,pos;}qu[maxn];map<int,int> mp;int ans[maxn];int sum[maxn],a[maxn],pre[maxn];bool cmp(Node xx,Node yy){    return xx.r<yy.r;}int main(){#ifdef LOCALfreopen("C:\\Users\\lanjiaming\\Desktop\\acm\\in.txt","r",stdin);//freopen("output.txt","w",stdout);#endif//ios_base::sync_with_stdio(0);    scanf("%d",&n);    sum[0] = 0;    //mp.clear();memset(ans,0,sizeof(ans));    for(int i = 1; i <= n; i++)    {        scanf("%d",&a[i]);        sum[i] = sum[i-1]^a[i];        pre[i] = mp[a[i]];        mp[a[i]] = i;    }    int q;    scanf("%d",&q);    for(int i = 1; i <= q; i++)    {        scanf("%d%d",&qu[i].l,&qu[i].r);        qu[i].pos = i;    }    sort(qu+1,qu+q+1,cmp);    int j = 1;    for(int i = 1; i <= q; i++)    {        for( ;j <= qu[i].r; j++)        {            if (pre[j]) ADD(pre[j],a[j]);            ADD(j,a[j]);        }        ans[qu[i].pos] = sum[qu[i].r]^sum[qu[i].l-1]^SUM(qu[i].r)^SUM(qu[i].l-1);    }    for(int i = 1; i <= q; i++) printf("%d\n",ans[i]);    return 0;}


0 0
原创粉丝点击