棠梨煎雪
题意:
给定m个字符串,由0,1,?构成,每次询问[l,r]中有多少种字符串S,能使得区间所有字符串均可以通过改变?来得到
以及单点修改字符串操作
思路:
显然当区间字符串在相同位置同时出现0,1是无解的
如果有位置是0或1,一定把?替换成0或1
剩下来的?都有两种选择,所以答案为2^(?的数量)
考虑用线段树维护
用两个二进制数维护每个字符串的01情况
对于字符串T,它每一位为1的位a也同样为1,其他位为0
它每一位为0的位b为1,其他位为0
那么检查是否矛盾,只需要看a&b是否大于0
pushup部分用|维护
int a[maxn];
int b[maxn];
struct node{
int l,r;
int ao,bo;
}tr[4*maxn];
void pushup(int p){
tr[p].ao=tr[ls].ao|tr[rs].ao;
tr[p].bo=tr[ls].bo|tr[rs].bo;
}
pii cal(string s){
int k=0,p=0;
for(int i=0;i<s.size();i++){
if(s[i]=='1'){
k|=(1ll<<i);
}else if(s[i]=='0'){
p|=(1ll<<i);
}
}
return {k,p};
}
void build(int p,int l,int r){
tr[p].l=l;tr[p].r=r;
if(l==r){
tr[p].ao=a[l];
tr[p].bo=b[l];
return;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(p);
}
node query(int p,int l,int r){
if(l<=tr[p].l&&tr[p].r<=r){
return tr[p];
}
int mid=tr[p].l+tr[p].r>>1;
if(r<=mid){
return query(ls,l,r);
}else if(l>mid){
return query(rs,l,r);
}else{
node ans;
node left=query(ls,l,r);
node right=query(rs,l,r);
ans.ao=left.ao|right.ao;
ans.bo=left.bo|right.bo;
return ans;
}
}
void change(int p,int pos,string s){
if(tr[p].l==tr[p].r){
pii res=cal(s);
a[pos]=res.fi;
b[pos]=res.se;
tr[p].ao=res.fi;
tr[p].bo=res.se;
return ;
}
int mid=tr[p].l+tr[p].r>>1;
if(pos<=mid)change(ls,pos,s);
else change(rs,pos,s);
pushup(p);
}
void solve(){
int n,m,q;cin>>n>>m>>q;
rep(i,1,m){
string s;cin>>s;
pii t=cal(s);
a[i]=t.fi;
b[i]=t.se;
}
build(1,1,m);
// rep(i,1,m){
// debug(a[i]);
// debug(b[i]);
// }
int ans=0;
while(q--){
int opt;cin>>opt;
if(opt==0){
int l,r;cin>>l>>r;
node res=query(1,l,r);
if(res.ao&res.bo)continue;
ans^=(1ll<<(n-__builtin_popcount(res.ao|res.bo)));
}else{
int pos;cin>>pos;
string t;cin>>t;
change(1,pos,t);
}
}
cout<<ans<<endl;
}

浙公网安备 33010602011771号