苹果蓝17
2020-11-22 10:16:21
题目传送门
更不好的阅读体验
第一次写题解写得稍微详细点
给定长度为
为了方便这里记
首先,需要知道异或有结合律与交换律。
带修有些麻烦,先来考虑没有修改时如何计算答案。
最暴力的当然是枚举每个子区间并
用前缀和优化一下,判断就可以
由上面那个式子可以发现
所以如果用
考虑用 map
存,当然可以在统计
总共
单次计算已经很优了,来考虑带修。
然后会发现每次修改只会改变
答案维护和上面一样。
然而由于 map
常数太大了,貌似要用 unordered_map
才能卡过去……
请注意,
a_i,x \leq Y 不能说明a_i \oplus x \leq Y 。
别忘了long long
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m;
long long s[N];
long long ans;
long long ansxor,ansj,ansmax=0,ansmin=1e18;
unordered_map <long long,int> mp;
int main(){
scanf("%d%d",&n,&m);
mp[0]++;
for(int i=1;i<=n;i++){
int a;
scanf("%d",&a);
s[i]=s[i-1]^a;//前缀异或和
ans+=mp[s[i]],mp[s[i]]++;
}
for(int i=1;i<=m;i++){
int p,x;
scanf("%d%d",&p,&x);
ans-=mp[s[p]]-1,mp[s[p]]--;
ans+=mp[s[p]^x],mp[s[p]^x]++;
s[p]^=x;//将s[p]变为s[p]^x,同时更新答案
ansxor^=ans;
if(ans & 1ll) ansj++;
ansmax=max(ansmax,ans);
ansmin=min(ansmin,ans);
}
printf("%lld\n%lld\n%lld\n%lld\n",ansxor,ansj,ansmax,ansmin);
}