题解 传教
刚了一场没刚动
- 关于一类定长区间修改问题:差分之后发现每次修改会影响到的两个点在模区间长意义下同余,也许可以对依次对区间长根号分治
- 按位异或的优先级大于逻辑等于的优先级
那么发现如果对每个剩余系单独维护一个序列
这个序列的前缀异或和中非零数的个数和就是答案
那么要支持的操作就是单点修改,区间异或和查询区间内值为 0 的个数
值域很小所以可以开桶
那么大力分块就可以了
复杂度 \(O(q\sqrt n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long
int n, k, q;
char op[N];
int a[N], b[N], t[N];
namespace force{
int recalc() {
int ans=0;
for (int i=1; i<=n; ++i) t[i]=a[i]^b[i];
for (int i=1; i<=n-k+1; ++i) if (t[i]) {
++ans;
for (int j=i+k-1; j>=i; --j) t[j]^=t[i];
}
for (int i=n-k+2; i<=n; ++i) if (t[i]) return -1;
return ans;
}
void solve() {
printf("%d\n", recalc());
for (int i=1,x,y; i<=q; ++i) {
scanf("%s%d%d", op, &x, &y);
if (*op=='a') a[x]=y;
else b[x]=y;
printf("%d\n", recalc());
}
}
}
namespace task1{
int bit[5010];
inline void upd(int i, int dat) {for (; i<=n; i+=i&-i) bit[i]^=dat;}
inline int query(int i) {int ans=0; for (; i; i-=i&-i) ans^=bit[i]; return ans;}
int recalc() {
int ans=0;
memset(bit, 0, sizeof(bit));
for (int i=1; i<=n; ++i) t[i]=a[i]^b[i];
for (int i=1; i<=n; ++i) upd(i, t[i]^t[i-1]);
for (int i=1; i<=n-k+1; ++i) if (t[i]=query(i)^query(i-1)) {
++ans;
upd(i, t[i]); upd(i+k, t[i]);
}
for (int i=n-k+2; i<=n; ++i) if (query(i)^query(i-1)) return -1;
return ans;
}
void solve() {
printf("%d\n", recalc());
for (int i=1,x,y; i<=q; ++i) {
scanf("%s%d%d", op, &x, &y);
if (*op=='a') a[x]=y;
else b[x]=y;
printf("%d\n", recalc());
}
}
}
namespace task2{
int siz[N], sqr, igl, ans;
struct rest{
int *buc, *tag, *bel, (*cnt)[1<<15], len, now, lst, id;
void build(int siz, int i) {
len=siz; id=i;
buc=new int[siz+3];
tag=new int[siz+3];
bel=new int[siz+3];
cnt=new int[(len-1)/sqr+2][1<<15];
for (int i=1; i<=len; ++i) bel[i]=(i-1)/sqr+1;
}
inline void pb(int t) {++now; ++cnt[bel[now]][buc[now]=buc[now-1]^t];}
void upd(int l, int r, int dat) {
int sid=bel[l], eid=bel[r];
if (sid==eid) {
for (int i=l; i<=r; ++i) --cnt[sid][buc[i]], ++cnt[sid][buc[i]^=dat];
return ;
}
for (int i=l; bel[i]==sid; ++i) --cnt[sid][buc[i]], ++cnt[sid][buc[i]^=dat];
for (int i=sid+1; i<eid; ++i) tag[i]^=dat;
for (int i=r; bel[i]==eid; --i) --cnt[eid][buc[i]], ++cnt[eid][buc[i]^=dat];
}
int qzero(int l, int r) {
int sid=bel[l], eid=bel[r], ans=0;
if (sid==eid) {
for (int i=l; i<=r; ++i) if ((buc[i]^tag[sid])==0) ++ans;
return ans;
}
// cout<<"buc: "; for (int i=1; i<=len; ++i) cout<<(buc[i]^tag[bel[i]])<<' '; cout<<endl;
for (int i=l; bel[i]==sid; ++i) if ((buc[i]^tag[sid])==0) ++ans;
for (int i=sid+1; i<eid; ++i) ans+=cnt[i][tag[i]];
for (int i=r; bel[i]==eid; --i) if ((buc[i]^tag[eid])==0) ++ans;
return ans;
}
int qval(int i) {return buc[i]^tag[bel[i]];}
void init() {if (id!=(n-k+1)%k && qval(len)) ++igl; ans+=(lst=qzero(1, len));}
void show() {for (int i=1; i<=len; ++i) cout<<(buc[i]^tag[bel[i]])<<' '; cout<<endl;}
void upd(int i, int dat) {
if (id!=(n-k+1)%k && qval(len)) --igl; ans-=lst;
upd(i, len, dat);
if (id!=(n-k+1)%k && qval(len)) ++igl; ans+=(lst=qzero(1, len));
// cout<<"new: "<<lst<<endl;
}
}grp[N];
void solve() {
sqr=sqrt(n);
for (int i=1; i<=n; ++i) t[i]=a[i]^b[i];
for (int i=n; i; --i) t[i]=t[i]^t[i-1];
// cout<<"t: "; for (int i=1; i<=n; ++i) cout<<t[i]<<' '; cout<<endl;
for (int i=1; i<=n; ++i) ++siz[i%k];
for (int i=0; i<k; ++i) grp[i].build(siz[i], i);
for (int i=1; i<=n; ++i) grp[i%k].pb(t[i]);
for (int i=0; i<k; ++i) grp[i].init();
// for (int i=0; i<k; ++i) grp[i].show();
if (k==1) igl=0;
printf("%d\n", igl?-1:n-ans);
for (int i=1,x,y,lst; i<=q; ++i) {
scanf("%s%d%d", op, &x, &y);
lst=a[x]^b[x];
if (*op=='a') a[x]=y;
else b[x]=y;
grp[x%k].upd((x-1)/k+1, lst^a[x]^b[x]);
if (x<n) grp[(x+1)%k].upd(x/k+1, lst^a[x]^b[x]);
t[x]^=lst^a[x]^b[x]; t[x+1]^=lst^a[x]^b[x];
// cout<<"t: "; for (int i=1; i<=n; ++i) cout<<t[i]<<' '; cout<<endl;
if (k==1) igl=0;
printf("%d\n", igl?-1:n-ans);
}
}
}
namespace task3{
int siz[N], sqr, igl, ans;
struct rest{
int *buc, *tag, *bel, (*cnt)[1<<15], len, now, lst, id;
void build(int siz, int i) {
len=siz; id=i;
buc=new int[siz+3];
}
inline void pb(int t) {++now; buc[now]=buc[now-1]^t;}
void upd(int l, int r, int dat) {for (int i=l; i<=r; ++i) buc[i]^=dat;}
int qzero(int l, int r) {
int ans=0;
for (int i=l; i<=r; ++i) if (buc[i]==0) ++ans;
return ans;
}
int qval(int i) {return buc[i];}
void init() {if (id!=(n-k+1)%k && qval(len)) ++igl; ans+=(lst=qzero(1, len));}
void show() {for (int i=1; i<=len; ++i) cout<<(buc[i]^tag[bel[i]])<<' '; cout<<endl;}
void upd(int i, int dat) {
if (id!=(n-k+1)%k && qval(len)) --igl; ans-=lst;
upd(i, len, dat);
if (id!=(n-k+1)%k && qval(len)) ++igl; ans+=(lst=qzero(1, len));
// cout<<"new: "<<lst<<endl;
}
}grp[N];
void solve() {
sqr=sqrt(n);
for (int i=1; i<=n; ++i) t[i]=a[i]^b[i];
for (int i=n; i; --i) t[i]=t[i]^t[i-1];
// cout<<"t: "; for (int i=1; i<=n; ++i) cout<<t[i]<<' '; cout<<endl;
for (int i=1; i<=n; ++i) ++siz[i%k];
for (int i=0; i<k; ++i) grp[i].build(siz[i], i);
for (int i=1; i<=n; ++i) grp[i%k].pb(t[i]);
for (int i=0; i<k; ++i) grp[i].init();
// for (int i=0; i<k; ++i) grp[i].show();
if (k==1) igl=0;
printf("%d\n", igl?-1:n-ans);
for (int i=1,x,y,lst; i<=q; ++i) {
scanf("%s%d%d", op, &x, &y);
lst=a[x]^b[x];
if (*op=='a') a[x]=y;
else b[x]=y;
grp[x%k].upd((x-1)/k+1, lst^a[x]^b[x]);
if (x<n) grp[(x+1)%k].upd(x/k+1, lst^a[x]^b[x]);
t[x]^=lst^a[x]^b[x]; t[x+1]^=lst^a[x]^b[x];
// cout<<"t: "; for (int i=1; i<=n; ++i) cout<<t[i]<<' '; cout<<endl;
if (k==1) igl=0;
printf("%d\n", igl?-1:n-ans);
}
}
}
signed main()
{
freopen("mission.in", "r", stdin);
freopen("mission.out", "w", stdout);
scanf("%d%d%d", &n, &k, &q);
for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
for (int i=1; i<=n; ++i) scanf("%d", &b[i]);
// force::solve();
// task1::solve();
if (k<=sqrt(n)) task2::solve();
else task3::solve();
return 0;
}