矿洞:坍塌

为什么不试试手写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("
%c%d%d",&p,&l,&r);
		if(p=='A'){
			scanf("
%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