P5522 [yLOI2019] 棠梨煎雪
题目背景
岁岁花藻檐下共将棠梨煎雪,
自总角至你我某日辗转天边。
天淡天青,宿雨沾襟,
一年一会信笺却只见寥寥数言。
——银临《棠梨煎雪》
题目描述
歌词中的主人公与她的朋友一年会有一次互相写信给对方,一共通信了 m 年。为了简化问题,我们认为她们每封信的内容都是一条二进制码,并且所有二进制码的长度都是 n。即每封信的内容都是一个长度为 n 的字符串,这个字符串只含字符 0
或 1
。
这天她拿出了朋友写给她的所有信件,其中第 i 年的写的信件编号为 i。由于信件保存时间过久,上面有一些字符已经模糊不清,我们将这样的位置记为 ?
,?
字符可以被解释为 0
或 1
。由于她的朋友也是人,符合人类的本质,所以朋友在一段连续的时间中书写的内容可能是相同的。现在她想问问你,对于一段连续的年份区间 [l,r] 中的所有信件,假如朋友在这段时间展示了人类的本质,所写的是同一句话,那么这一句话一共有多少种可能的组成。也即一共有多少字符串 S,满足在这个区间内的所有信件的内容都可能是 S。
一个长度为 n 的只含 0,1,?
的字符串 A 可能是一个字符串 B 当且仅当 B 满足如下条件:
- B 的长度也是 n 。
- B 中只含字符
0,1
。 - A 中所有为
0
的位置在 B 中也是0
。 - A 中所有为
1
的位置在 B 中也是1
。 - A 中为
?
的位置在 B 中可以为0
也可以是1
。
同时她可能会突然发现看错了某年的信的内容,于是她可能会把某一年的信的内容修改为一个别的只含 0
,1
,?
的长度为 n 的字符串。
输入格式
每个输入文件中都有且仅有一组测试数据。
输入数据第一行为三个用空格隔开的整数,分别代表代表字符串长度 n,字符串个数 m 和操作次数 q。
下面 m 行,每行是一个长度为 n 的字符串,第 (i+1) 行的字符串 s**i 代表第 i 年信的内容。
下面 q 行,每行的第一个数字是操作编号 opt。
- 如果 opt=0,那么后面接两个整数 [l, r],代表一次查询操作。
- 如果 opt=1,那么后面接一个整数 pos,在一个空格后会有一个长度为 n 的字符串 t,代表将第 pos 个字符串修改为新的字符串 t。
输出格式
为了避免输出过大,请你输出一行一个数代表所有查询的答案异或和对 0 取异或的结果。
题解
注意到每一位是独立的之后就不难想到对于每一位建个线段树,复杂度 \(\text O(nq\log m)\) 得到了70分的好成绩
其实发现可以将 0
赋成 01
、1
赋成 10
、?
赋成 11
,就可以得到下面运算:
0
&0
=0
;1
&1
=1
?
&0
=0
;?
&1
=1
?
&?
=?
于是就可以把30颗线段树压成一个 ull
,就可以顺利压到 \(\text O(q\log m)\) 了
#include<bits/stdc++.h>
#define int unsigned long long
#define jk(i,j,k) for(int i=(j);i<=(k);i++)
#define kj(i,j,k) for(int i=(j);i>=(k);i--)
int rd(){int data=0,w=1;char ch=0;while(ch!='-'&&(ch>'9'||ch<'0'))ch=getchar();(ch=='-')&&(w=-1,ch=getchar());while(ch>='0'&&ch<='9'){data=data*10+ch-'0';ch=getchar();}return data*w;}
void P(int v){if(v<0){putchar('-');v=-v;}if(v>9)P(v/10);putchar(v%10+'0');}
#define N 40
#define M 100010
#define lc o<<1
#define rc o<<1|1
int fl[N*N],n,q,o,l,r,R,B[N],E,m,g[M];
char s[N];
struct No{int l,r;int s;}t[M<<2];
int Bi(int X){int r=1;jk(i,1,n)r*=B[X%4],X>>=2;return r;}
void upd(int o){t[o].s=t[lc].s&t[rc].s;}
void bui(int o,int l,int r){
t[o].l=l;t[o].r=r;
if(l==r){t[o].s=g[l];return;}
int mi=(l+r)>>1;
bui(lc,l,mi);bui(rc,mi+1,r);upd(o);
}
void cha(int o,int x,int d){
if(x<t[o].l||x>t[o].r)return;
if(t[o].l==t[o].r){t[o].s=d;return;}
cha(lc,x,d);cha(rc,x,d);upd(o);
}
int que(int o,int l,int r){
if(r<t[o].l||l>t[o].r)return (1ull<<63)-1ull;
if(l<=t[o].l&&r>=t[o].r)return t[o].s;
return que(lc,l,r)&que(rc,l,r);
}
signed main(){
B[fl['0']=1]=1;B[fl['1']=2]=1;B[fl['?']=3]=2;
n=rd();m=rd();q=rd();
jk(i,1,m){scanf("%s",s+1);jk(j,1,n)g[i]=g[i]<<2|fl[s[j]];}
bui(1,1,m);
jk(Q,1,q){
o=rd();l=rd();
if(o){scanf("%s",s+1);jk(i,1,n)m=m<<2|fl[s[i]];cha(1,l,m);}
else E^=Bi(que(1,l,rd()));
}
P(E);
}