矿洞:坍塌

为什么不试试手写bitset呢QAQ

存在字符x对应二进制第x-'A'位为1

这样就是线段树维护区间或了

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;

const int MAXN=1<<19;
const int siz=3;

int n,m;
char ch[MAXN];
int tag[MAXN<<1],tree[MAXN<<1];

void build(int k,int l,int r)
{
    tag[k]=-1;
    if(l==r){
        tree[k]=1<<(ch[l]-'A');
        return;
    }int i=k<<1,mid=l+r>>1;
    build(i,l,mid);build(i|1,mid+1,r);
    tree[k]=tree[i]|tree[i|1];
    return;
}

void po(int k,int l,int r)
{
    if(l==r||tag[k]==-1) return;
    int i=k<<1;
    tree[i]=tree[i|1]=1<<tag[k];
    tag[i]=tag[i|1]=tag[k];
    tag[k]=-1;
    return;
}

void cchg(int k,int l,int r,int le,int ri,int x)
{
    po(k,l,r);
    if(le<=l&&r<=ri){
        tree[k]=1<<x;
        tag[k]=x;
        return;
    }int i=k<<1,mid=l+r>>1;
    if(le<=mid) cchg(i,l,mid,le,ri,x);
    if(mid<ri) cchg(i|1,mid+1,r,le,ri,x);
    tree[k]=tree[i]|tree[i|1];
    return;
}

int cask(int k,int l,int r,int le,int ri)
{
    po(k,l,r);
    if(le<=l&&r<=ri) return tree[k];
    int ans=0;
    int i=k<<1,mid=l+r>>1;
    if(le<=mid) ans|=cask(i,l,mid,le,ri);
    if(mid<ri) ans|=cask(i|1,mid+1,r,le,ri);
    return ans;
}

int count(int x)
{
    int sum=0;
    while(x) ++sum,x&=x-1;
    return sum;
}

int main()
{
    scanf("%d",&n);
    scanf("%s",ch+1);
    build(1,1,n);
    scanf("%d",&m);
    while(m--){
        char p,c;int l,r;
        scanf("\n%c%d%d",&p,&l,&r);
        if(p=='A'){
            scanf("\n%c",&c);
            cchg(1,1,n,l,r,(int)c-'A');
        }else{
            if(l==1||r==n){
                int ct=cask(1,1,n,l,r);
                if(count(ct)==1) puts("Yes");
                else puts("No");
            }else{
                int ct=cask(1,1,n,l,r),tp1=cask(1,1,n,l-1,l-1),tp2=tp1|cask(1,1,n,r+1,r+1);
                if(count(ct)==1&&count(tp2)==2) puts("Yes");
                else puts("No");
            }
        }
    }return 0;
}

转载于:https://www.cnblogs.com/AH2002/p/10058770.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值