[cf1083F]The Fair Nut and Amusing Xor
令$c_{i}=a_{i}\oplus b_{i}$,那么也就是要对$c_{i}$执行操作使其变为0
显然有一个贪心的策略,即从左往右,若当前$c_{i}\ne 0$,则执行对$[i,i+k)$异或$c_{i}$的操作,若$i+k\ge n+2$则说明无解
更具体的,定义$p_{i}$为到第$i$个位置上时第$i$个位置上的操作,那么有$p_{i}=p_{i-k}\oplus c_{i-1}\oplus c_{i}$(特别的,$c_{0}=0$,若$i\le 0$则$p_{i}=0$)
解释一下,除去$p_{i-k}$以外,当前所有操作都是$i-1$和$i$一起执行,不难发现这些操作的总影响是$p_{i-k}\oplus c_{i-1}$,初始是$c_{i}$,再异或一下即为当前的值
我们所求的即为$p_{i}$中非0的个数以及判定$p_{i}$($i\ge n-k+2$)是否存在非0数(即无解)
令$c'_{i}=c_{i}\oplus c_{i-1}$,记第$i$组为模$k$余$i$的$j$($1\le j\le n$)的$c'_{j}$所构成的序列($0\le i<k$,不改变相对顺序),每一组显然独立,且对于第$i$组,需要以下两个信息:
1.所有数异或的结果,若存在$i\not\equiv n-k+1(mod\ k)$且结果不为0,则无解
2.前缀异或和中非0数的个数,这个即为答案
对于第一个修改可以很容易支持(维护0的个数),对于第二个直接记录前缀异或和,那么修改即支持后缀异或的操作以及统计非0的个数,也就是全部减去0的个数
再对每一组内部分块,设块大小为$K$,对于每一个块维护桶以及修改懒标记,考虑复杂度:
时间复杂度为$o((\frac{n}{K}+K)q)$,取$K=\sqrt{n}$即为$o(q\sqrt{n})$
空间复杂度为$o(\frac{2^{14}n}{K})$,在最优时间复杂度的取值下可以接受
另外还有一个特殊情况,当$k$较大时每一个块的大小无法达到$K$(如$k=n$时空间会退化为$o(2^{14}n)$),更具体的,当$k>\sqrt{n}$,对每一个块暴力处理,复杂度为$o(\frac{n}{k}q)$,与之前相同
其他情况下,即使每一组恰好多出一个大小为1的块,也就至多多$\sqrt{n}$个块,并没有太大影响

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define NN 1005
5 int n,k,q,K,x,y,sp,flag,ans_sum,a[N],b[N],cc[N],c[N],len[N],check[N],ans[N];
6 int bl[N],id[NN][NN],tag[N],tot[NN][(1<<14)];
7 char s[11];
8 void add(int k){
9 if (k!=sp)flag+=(check[k]>0);
10 ans_sum+=ans[k];
11 }
12 void del(int k){
13 if (k!=sp)flag-=(check[k]>0);
14 ans_sum-=ans[k];
15 }
16 void add(int x,int i){
17 tot[id[x][i/K]][c[i*k+x]]++;
18 if (c[i*k+x]==tag[id[x][i/K]])ans[x]++;
19 }
20 void del(int x,int i){
21 tot[id[x][i/K]][c[i*k+x]]--;
22 if (c[i*k+x]==tag[id[x][i/K]])ans[x]--;
23 }
24 void update(int x,int y){
25 del(bl[x]);
26 check[bl[x]]^=y;
27 int i=(x-bl[x])/k;
28 if (k>K){
29 for(;i<len[bl[x]];i++){
30 if (!c[i*k+bl[x]])ans[bl[x]]--;
31 c[i*k+bl[x]]^=y;
32 if (!c[i*k+bl[x]])ans[bl[x]]++;
33 }
34 }
35 else{
36 for(;(i<len[bl[x]])&&(i%K);i++){
37 del(bl[x],i);
38 c[i*k+bl[x]]^=y;
39 add(bl[x],i);
40 }
41 if (i!=len[bl[x]]){
42 for(;i<len[bl[x]];i+=K){
43 ans[bl[x]]-=tot[id[bl[x]][i/K]][tag[id[bl[x]][i/K]]];
44 tag[id[bl[x]][i/K]]^=y;
45 ans[bl[x]]+=tot[id[bl[x]][i/K]][tag[id[bl[x]][i/K]]];
46 }
47 }
48 }
49 add(bl[x]);
50 }
51 void write(){
52 if (flag)printf("-1\n");
53 else printf("%d\n",n-ans_sum);
54 }
55 int main(){
56 scanf("%d%d%d",&n,&k,&q);
57 K=(int)sqrt(n);
58 for(int i=0;i<n;i++)scanf("%d",&a[i]);
59 for(int i=0;i<n;i++)scanf("%d",&b[i]);
60 sp=n%k;
61 for(int i=0;i<n;i++){
62 bl[i]=i%k;
63 len[bl[i]]++;
64 cc[i]=(a[i]^b[i]);
65 }
66 c[0]=cc[0];
67 for(int i=1;i<n;i++)c[i]=(cc[i-1]^cc[i]);
68 for(int i=k;i<n;i++)c[i]=(c[i]^c[i-k]);
69 for(int i=n-k;i<n;i++)check[bl[i]]=c[i];
70 if (k>K){
71 for(int i=0;i<n;i++)ans[bl[i]]+=(c[i]==0);
72 }
73 else{
74 int V=0;
75 for(int i=0;i<k;i++)
76 for(int j=0;j<len[i];j+=K)id[i][j/K]=++V;
77 for(int i=0;i<n;i++)add(bl[i],(i-bl[i])/k);
78 }
79 for(int i=0;i<k;i++)add(i);
80 write();
81 for(int i=1;i<=q;i++){
82 scanf("%s%d%d",s,&x,&y);
83 x--;
84 if (s[0]=='a'){
85 update(x,(a[x]^y));
86 if (x<n-1)update(x+1,(a[x]^y));
87 a[x]=y;
88 }
89 else{
90 update(x,(b[x]^y));
91 if (x<n-1)update(x+1,(b[x]^y));
92 b[x]=y;
93 }
94 write();
95 }
96 }
[cf1083F]The Fair Nut and Amusing Xor的更多相关文章
- [CF1083F]The Fair Nut and Amusing Xor[差分+同余分类+根号分治+分块]
题意 给定两个长度为 \(n\) 的序列 \(\{a_i\}\) 与 \(\{b_i\}\),你需要求出它们的相似度.,我们定义这两个序列的相似度为将其中一个序列转化为另一个序列所需的最小操作次数.一 ...
- CF1083E The Fair Nut and Rectangles
CF1083E The Fair Nut and Rectangles 给定 \(n\) 个平面直角坐标系中左下角为坐标原点,右上角为 \((x_i,\ y_i)\) 的互不包含的矩形,每一个矩形拥有 ...
- CF 1083 B. The Fair Nut and Strings
B. The Fair Nut and Strings 题目链接 题意: 在给定的字符串a和字符串b中找到最多k个字符串,使得不同的前缀字符串的数量最多. 分析: 建出trie树,给定的两个字符串就 ...
- CF 1083 A. The Fair Nut and the Best Path
A. The Fair Nut and the Best Path https://codeforces.com/contest/1083/problem/A 题意: 在一棵树内找一条路径,使得从起点 ...
- CF1083A The Fair Nut and the Best Path
CF1083A The Fair Nut and the Best Path 先把边权搞成点权(其实也可以不用),那么就是询问树上路径的最大权值. 任意时刻权值非负的限制可以不用管,因为若走路径 \( ...
- Codeforces Round #526 (Div. 2) E. The Fair Nut and Strings
E. The Fair Nut and Strings 题目链接:https://codeforces.com/contest/1084/problem/E 题意: 输入n,k,k代表一共有长度为n的 ...
- Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path
D. The Fair Nut and the Best Path 题目链接:https://codeforces.com/contest/1084/problem/D 题意: 给出一棵树,走不重复的 ...
- Codeforces Round #526 (Div. 2) C. The Fair Nut and String
C. The Fair Nut and String 题目链接:https://codeforces.com/contest/1084/problem/C 题意: 给出一个字符串,找出都为a的子序列( ...
- C. The Fair Nut and String 递推分段形dp
C. The Fair Nut and String 递推分段形dp 题意 给出一个字符串选择一个序列\({p_1,p_2...p_k}\)使得 对于任意一个\(p_i\) , \(s[p_i]==a ...
随机推荐
- 洛谷4051 JSOI2007 字符加密(SA)
真是一道良好的SA模板题 首先,由于涉及到从左边移动到右边这个过程,我们不妨直接把字符串复制一遍,接在后面. 然后直接构造后缀数组,按排名从小到大,枚举所有的位置,如果这个后缀的起始点是在原串中的,那 ...
- pycharm输入代码后,没有补全提示
安装pycharm后,输入代码后,没有补全提示 首先检查是否关闭了代码提示,如下图,将红框中"Power Save Mode"前的勾去掉 第二步,如果在输入某些代码时还是没有补全提 ...
- 【UE4】异步加载关卡 LoadingScreen ( 蓝图和C++ )
一般先跳转到一个临时的关卡,然后异步加载目标关卡,同时展示Loading界面 对于含有流关卡的目标关卡,可以先载入子关卡 蓝图异步加载 无进度条 C++ 异步加载关卡 LoadPackageAsync ...
- 【UE4 设计模式】设计模式一些概念
定义 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结. 使用设计模式是为了重用代码.让代码更容易被他人理解.保证代码可靠性. 四人帮 GOF ( Gang of Four ...
- ffmpeg剪视频
ffmpeg裁剪合并视频 ffmpeg提供简单的命令参数: ffmpeg -ss START -t DURATION -i INPUT -vcodec copy -acodec copy OUTP ...
- [no code][scrum meeting] Alpha 13
项目 内容 会议时间 2020-04-21 会议主题 OCR技术对接会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalo ...
- [火星补锅] 水题大战Vol.2 T1 && luogu P1904 天际线 题解 (线段树)
前言: 当时考场上并没有想出来...后来也是看了题解才明白 解析: 大家(除了我)都知道,奇点和偶点会成对出现,而出现的前提就是建筑的高度突然发生变化.(这个性质挺重要的,我之前没看出来) 所以就可以 ...
- 三极管和MOS管驱动电路的正确用法
1 三极管和MOS管的基本特性 三极管是电流控制电流器件,用基极电流的变化控制集电极电流的变化.有NPN型三极管(简称P型三极管)和PNP型三极管(简称N型三极管)两种,符号如下: MOS管是电压控制 ...
- SpringCloud微服务实战——搭建企业级开发框架(九):使用Nacos发现、配置和管理微服务
Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台,Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置 ...
- 算法:杨辉三角(Pascal's Triangle)
一.杨辉三角介绍 杨辉三角形,又称帕斯卡三角形.贾宪三角形.海亚姆三角形.巴斯卡三角形,是二项式系数的一种写法,形似三角形,在中国首现于南宋杨辉的<详解九章算法>得名,书中杨辉说明是引自贾 ...