2024牛客多校D.XOR of Suffix Sums

题目

题目要求的是求后缀和的异或和。首先我们考虑疑惑和情况下,什么时候为1,很显然,在当前二进制位0和1 的其中任意一个个数为奇数的时候才能让当前二进制位为1。

再观察到,题目中的模数很奇怪,他是2^{21}。那么大于2^{21}的数位都是不用考虑的。

变化的后缀和很好维护,但是难就难在求玩后缀和后的异或和上面。(赛时就没想明白,太弱了)

这个时候我们搬出树状数组用来统计每个数对相应的二进制位上的贡献。

ps:有一个点需要想一下,我如何去判断一个数只能对当前二进制位产生贡献。如果一个数相对当前二进制位产生贡献,那么我们就可以先将其对下一个更大的二进制位进行取模(限制上限)如果取完模之后发现大于当前二进制位,那么就很显然,能对当前位作出贡献。

举个例子:计算11这个数是否对第四个二进制位(8)作出贡献。首先11%16(8的下一个二进制位)=11;11>8,那么11就会对第四个二进制位作出贡献。那么此时就在树状数组记录第八位贡献下,从8开始++。

如此一来,就能决解统计问题了。随后就要解决查询问题。题目最后要求输出后缀和的异或和。

那么我们只需要逆推,依次计算对应二进制位上的1的数量就行


#include <cassert>
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cwchar>
#include <cwctype>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
// #include<priirity_queue>
#define lowbit(x) (x&(-x))
#define ll long long
#define int long long
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
// #define endl "\n"
#define pii pair<ll,ll>
#define psi pair<string, ll>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define ls u << 1
#define rs u << 1 | 1
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
// static char buf[100000],*pa=buf,*pd=buf;
// #define gc pa==pd&&(pd=(pa=buf)+fread(buf,1,100000,stdin),pa==pd)?EOF:*pa++
// inline int read()
// {
//     register int x(0);register char c(gc);
//     while(c<'0'||c>'9')c=gc;
//     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=gc;
//     return x;
// }
const int mod1 = 998244353;
const int mod2=1e9+7;
const int N = 3e6 + 60;
const ll INF = 1e15;
int n, m, k;
int z,len;
const int MOD=2097152;
int tr[25][MOD<<1];
int d[25];
int sum[N];
void add(int a[],int x,int k)
{
	x+=1;
	for(int i=x;i<=MOD;i+=lowbit(i))
	{
		a[i]+=k;
	}
}
int findd(int a[],int x)
{
   x+=1;
	int	ans=0;
	for(int i=x;i;i-=lowbit(i))ans+=a[i];
	return ans; 
}
void solve()
{
	len=0;
	d[0]=1;
	for(z=1;;z++)
	{
		d[z]=d[z-1]*2;
		if(d[z]==MOD)
		{
			z--;
			break;
		}
		
	}
	rep(i,0,z)
	{
		add(tr[i],0,1);
	}
	//cout << 1 <<endl;
	int t;
	cin >> t;
	while(t--)
	{
		int a,b;
		cin >> a >> b;
		while(a--)
		{
			rep(i,0,z)
			{
				add(tr[i],sum[len]%d[i+1],-1);
			}
			len--;
		}
		len++;
		sum[len]=sum[len-1]+b;
		rep(i,0,z)
		{
			add(tr[i],sum[len]%d[i+1],1);
		} 
		int ans=0;
		rep(i,0,z)
		{
			int ant=sum[len]%d[i+1];
			int num=0;
			if(ant-d[i]>=0)
			{
				num+=findd(tr[i],ant-d[i]);
			}
			num += findd(tr[i],ant +d[i])-findd(tr[i],ant);
			num%=2;
			ans += num*d[i];
		}
		cout << ans <<endl;
	}
}



signed main()
{
	IOS;
	int _;
	_ = 1;
	//cin >> _;
	
	while(_ --) 
	{
		// number++;
		solve();
	}
	return 0;
}  

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值