题解 传教

传送门

刚了一场没刚动

  • 关于一类定长区间修改问题:差分之后发现每次修改会影响到的两个点在模区间长意义下同余,也许可以对依次对区间长根号分治
  • 按位异或的优先级大于逻辑等于的优先级

那么发现如果对每个剩余系单独维护一个序列
这个序列的前缀异或和中非零数的个数和就是答案
那么要支持的操作就是单点修改,区间异或和查询区间内值为 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;
}
posted @ 2022-03-17 18:52  Administrator-09  阅读(3)  评论(0编辑  收藏  举报