Codeforces 703D
题目链接:http://acm.hust.edu.cn/vjudge/problem/450060
题目大意: 给出一个长度为n的序列a (a<=10^9),询问m次,每次询问区间[l,r]之内出现偶数个数的数的异或和。
分析:
我们先利用异或前缀和,这样问题转化为在区间[l,r]中出现过的数异或和。
对于这样一个问题,我们不妨先看另外一个问题:动态查询区间[l,r]内不同的数的个数。
我们先离线处理,将询问按右端点排序,设Last[val]为val在当前序列中最后一次出现的位置,cnt[i]=1 当且经当last[a[i]]=i,则答案即为[l,r]的cnt和。
当右端点移动时,用Fenwick Tree更新a[i]的值更新last和cnt,将之前的last值与cnt更新,在O(nlogn)的时间内求出答案。
再回到原问题,我们只需将求和改为异或和,将cnt[i]=1改为cnt[i]=a[i],离散化就解决了。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)
#define sz(x) (int)(x.size())
using namespace std;
typedef long long LL;
const int maxn=1000000+27;
struct node{
  int l,r,num,ans;
} q[maxn];
int T[maxn],last[maxn],a[maxn],s[maxn],u[maxn],size,n,m,k,last_r,prex[maxn],cnt[maxn];
bool cmp(node a,node b) {return a.r<b.r;}
bool cmp2(node a,node b) {return a.num<b.num;}
bool ucmp(int a,int b) {return s[a]<s[b];}
void init()  //离散化
{
  rep(i,1,n) u[i]=i;
  sort(u+1,u+n+1,ucmp);
  
  k=0,size=0;
  while (k<n)
  {
	k++,size++;
	while (k<=n)
	{
	  a[u[k]]=size;
	  if (s[u[k+1]]!=s[u[k]]) break;
	  k++;
    }
  }
}
void set(int x,int val) //修改cnt值
{
  int k=x;
  while (x<=n) T[x]=(T[x]^cnt[k])^val,x+=(x&(-x));
}
int sum(int x) //求异或和
{
  int s=0;
  while (x>0) s^=T[x],x-=(x&(-x));
  return s;
}
int main()
{
  scanf("%d",&n);
  rep(i,1,n) scanf("%d",&s[i]);
  
  init();
  
  scanf("%d",&m);
  rep(i,1,m)
  {
	scanf("%d%d",&q[i].l,&q[i].r);
	q[i].num=i;
  }
  
  sort(q+1,q+m+1,cmp); //对询问排序
  
  k=0,last_r=0;
	
  while (k<m)
  {
    k++;
	
	rep(i,last_r+1,q[k].r) //对相同右端点集中更新
	{
	  if (last[a[i]]) set(last[a[i]],0),cnt[last[a[i]]]=0;
	  last[a[i]]=i,set(i,s[i]),cnt[i]=s[i];	  
	}
    
	last_r=q[k].r;
	
	while (k<=m)
	{
	  q[k]. ans=sum(q[k].r)^sum(q[k].l-1);
	  if (q[k+1].r!=q[k].r) break;
	  k++;
	}
  }
  
  sort(q+1,q+m+1,cmp2);
  
  rep(i,1,n) prex[i]=prex[i-1]^s[i]; //前缀和
  rep(i,1,m) printf("%d\n",(q[i].ans)^(prex[q[i].r]^prex[q[i].l-1]));
  
  return 0;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号