[TJOI2017]异或和

\(ProblemLink\)

题目大意

求序列所有连续和的异或值

Solution

考虑单独每一个二进制位\(k\)

\(S_i=\sum\limits_{j=1}^ia[j],(S_0=0)\)

我们只需要知道\(\sum\limits_{i=1}^n\sum\limits_{j=0}^{i-1}(S(i)-S(j))\and (2^k)\)的奇偶性就可以知道答案中有没有k这一位

于是我们可以用权值树状数组统计,对于一个\(i\),前\(i-1\)个中有多少一个\(j\),\(S(i)-S(j)\)在k这一位上是1

假如\(S(i)\and 2^k=1\)

则答案就是在\(k\)这一位是0,且前\(k\)位小于\(S(i)\)\(S(j)\)的个数加上在\(k\)这一位是\(1\),且前\(k\)位大于\(S(i)\)\(S(j)\)的个数

\(S(i)\and 2^k=0\)类似

于是用权值树状数组统计即可,注意下标\(+1\)

update:FFT也可以做诶

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IL inline
#define RG register
#define gi geti<int>()
#define gl geti<ll>()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
template<typename T>IL bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template<typename T>IL bool chkmin(T &x,const T &y){return x>y?x=y,1:0;}
template<typename T>
IL T geti()
{
	RG T xi=0;
	RG char ch=gc;
	bool f=0;
	while(!isdigit(ch))ch=='-'?f=1:f,ch=gc;
	while(isdigit(ch))xi=xi*10+ch-48,ch=gc;
	return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
	if(k<0)k=-k,putchar('-');
	if(k>=10)pi(k/10);
	putchar(k%10+'0');
	if(ch)putchar(ch);
}
const int N=1e6+7;
struct BIT{
	int c[N];
	vector<int>cur;
#define lowbit(x) ((x)&(-x))
	inline void add(int x,int addv){
		for(;x<=N;x+=lowbit(x))
		{
			if(!c[x])cur.push_back(x);
			c[x]+=addv;
		}
	}
	inline int query(int x){
		int ret=0;
		for(;x;x-=lowbit(x))ret+=c[x];
		return ret;
	}
	inline void clear(void)
	{
		for(auto i:cur)c[i]=0;
		cur.clear();
	}
}bit[2];
int s[N],ans,a[N];
int main(void)
{
	int n=gi,mx=0;
	for(int i=1;i<=n;++i)s[i]=s[i-1]+gi,chkmax(mx,s[i]);
	for(int i=0;i<=20;++i)
	{
		if(mx<(1<<i))break;
		bit[0].clear(),bit[1].clear();
		bit[0].add(1,1);
		for(int j=1;j<=n;++j)
		{
			int tmp=(s[j]>>i)&1;
			if((bit[!tmp].query(a[j]+1)+bit[tmp].query(N)-bit[tmp].query(a[j]+1))&1)ans^=1<<i;
			bit[tmp].add(a[j]+1,1);
			a[j]|=tmp*(1<<i);
		}
	}
	pi(ans);
	return 0;
}
posted @ 2019-10-13 21:07  Adscn  阅读(83)  评论(0编辑  收藏  举报