Codeforces 899F Letters Removing [线段树]

题意:给你长度为n的只包含小写字母,大写字母和数字的串,每次操作是区间[L,R]的字符c删除,问最后的串是什么样子。

题解:我们可以通过开62个字符的线段树来维护区间和。

AC代码:

#include
#include
#define N 200005
char a[N];
int tree[N*4][62];
bool add[N*4][62];
int Get(char a)
{
	if(a>='a'&&a<='z')return a-'a';
	if(a>='A'&&a<='Z')return a-'A'+26;
	if(a>='0'&&a<='9')return a-'0'+52;
}
int Put(int num)
{
	if(num>=0&&num<26)return num+'a';
	if(num>=26&&num<52)return num+'A'-26;
	if(num>=52)return num+'0'-52;
}
void build(int L,int R,int root)
{
	if(L==R)
	{
		tree[root][Get(a[L])]++;
		return ;
	}
	int mid=L+R>>1;
	build(L,mid,root<<1);
	build(mid+1,R,root<<1|1);
	for(int i=0;i<62;i++)
		tree[root][i]=tree[root<<1][i]+tree[root<<1|1][i];
}
void pushdown(int root,int pos)
{
	tree[root<<1][pos]=0;
	tree[root<<1|1][pos]=0;
	add[root<<1][pos]=add[root<<1|1][pos]=add[root][pos];
	add[root][pos]=0;
}
int Find(int L,int R,int root,int k)
{
	if(L==R)return L;
	int mid=L+R>>1;
	int lsum=0;
	for(int i=0;i<62;i++)
		if(add[root][i])
			pushdown(root,i);
	for(int i=0;i<62;i++)
		lsum+=tree[root<<1][i];
	if(lsum>=k)return Find(L,mid,root<<1,k);
	else return Find(mid+1,R,root<<1|1,k-lsum);
	for(int i=0;i<62;i++)
		tree[root][i]=tree[root<<1][i]+tree[root<<1|1][i];
}
void update(int l,int r,int L,int R,int root,char k)
{
	if(l<=L&&R<=r)
	{
		tree[root][Get(k)]=0;
		add[root][Get(k)]=1;
		return ;
	}
	int mid=L+R>>1;
	for(int i=0;i<62;i++)
		if(add[root][i])
			pushdown(root,i);
	if(r<=mid)update(l,r,L,mid,root<<1,k);
	else if(l>mid)update(l,r,mid+1,R,root<<1|1,k);
	else 
	{
		update(l,mid,L,mid,root<<1,k);
		update(mid+1,r,mid+1,R,root<<1|1,k);
	}
	for(int i=0;i<62;i++)
		tree[root][i]=tree[root<<1][i]+tree[root<<1|1][i];
}
void travel(int L,int R,int root)
{
	if(L==R)
	{
		for(int i=0;i<62;i++)
			if(tree[root][i]!=0)
				printf("%c",Put(i));
		return ;
	}
	int mid=L+R>>1;
	for(int i=0;i<62;i++)
		if(add[root][i])
			pushdown(root,i);
	travel(L,mid,root<<1);
	travel(mid+1,R,root<<1|1);
}
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	scanf("%s",a+1);
	build(1,n,1);
	while(q--)
	{
		int l,r;
		char c[2];
		scanf("%d%d%s",&l,&r,c);
		l=Find(1,n,1,l);r=Find(1,n,1,r);
		update(l,r,1,n,1,c[0]);
	}
	travel(1,n,1);
	printf("\n");
}


你可能感兴趣的:(Codeforces,线段树)