棠梨煎雪

P5522 [yLOI2019] 棠梨煎雪

题意:

给定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;
}
posted @ 2025-06-11 15:10  Marinaco  阅读(7)  评论(0)    收藏  举报
//雪花飘落效果