[ybtoj 4.4.5/CF555E] A Simple Task [线段树]
题意
给定一个长度不超过 1 0 5 10^5 105 的字符串(小写英文字母),和不超过 1 0 5 10^5 105 个操作。
每个操作 l , r , k l,r,k l,r,k 表示给区间 [ l , r ] [l,r] [l,r] 的字符串排序, k = 1 k=1 k=1 为升序, k = 0 k=0 k=0 为降序。
最后输出最终的字符串。
题解
考虑到只有 26 26 26 个字母,尝试将每个字母暴力拆开做线段树。
具体来说就是在每次要求排序的时候将区间内的所有字母的数量取出,
设 a [ i ] a[i] a[i] 表示区间有 a [ i ] a[i] a[i] 个 i i i 字母
那么最后的排序方式即为:
a [ 1 ] a[1] a[1] 个 1 1 1 , a [ 2 ] a[2] a[2] 个 2 2 2 , a [ 3 ] a[3] a[3] 个 3 3 3 … \dots …
那么需要我们实现一个 区间加+区间覆盖 的线段树
然后就做完了
时间复杂度是自带 26 26 26 大常数的 O ( n l o g n ) O(nlogn) O(nlogn) (
代码
#include<bits/stdc++.h>
#define N 100010
#define l(x) (x<<1)
#define r(x) (x<<1|1)
#define s(x,y) seg[x][y].sum
#define tag(x,y) seg[x][y].tag
#define mid (l+r>>1)
using namespace std;
struct tree{
	int sum,tag;
}seg[27][N*4];
int a[N],n,m;
void build(int x,int l,int r)
{
	if(l==r){s(a[l],x)=1;return;}
	build(l(x),l,mid);build(r(x),mid+1,r);
	for(int i=1;i<=26;i++)s(i,x)=s(i,l(x))+s(i,r(x)),tag(i,x)=-1;
}
int query(int id,int x,int l,int r,int L,int R)
{
	if(L<=l&&r<=R)return s(id,x);
	if(tag(id,x)!=-1)
	{
		tag(id,l(x))=tag(id,r(x))=tag(id,x);
		s(id,l(x))=(mid-l+1)*tag(id,x);s(id,r(x))=(r-mid)*tag(id,x);
		tag(id,x)=-1;
	}
	if(R<=mid)return query(id,l(x),l,mid,L,R);
	if(mid<L)return query(id,r(x),mid+1,r,L,R);
	return query(id,l(x),l,mid,L,mid)+query(id,r(x),mid+1,r,mid+1,R);
}
void change(int id,int x,int l,int r,int L,int R,int num)
{
	if(L<=l&&r<=R){s(id,x)=(r-l+1)*num;tag(id,x)=num;return;}
	if(tag(id,x)!=-1)
	{
		tag(id,l(x))=tag(id,r(x))=tag(id,x);
		s(id,l(x))=(mid-l+1)*tag(id,x);s(id,r(x))=(r-mid)*tag(id,x);
		tag(id,x)=-1;
	}
	if(R<=mid)change(id,l(x),l,mid,L,R,num);
	else if(mid<L)change(id,r(x),mid+1,r,L,R,num);
	else change(id,l(x),l,mid,L,mid,num),change(id,r(x),mid+1,r,mid+1,R,num);
	s(id,x)=s(id,l(x))+s(id,r(x));
}
int main()
{
	char ch;int s[27],x,y,z;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)cin>>ch,a[i]=ch-96;
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&y,&z,&x);
		for(int j=1;j<=26;j++){s[j]=query(j,1,1,n,y,z);if(s[j])change(j,1,1,n,y,z,0);}
		if(x==1){for(int j=1,k=y-1;j<=26;k+=s[j],j++)if(s[j])change(j,1,1,n,k+1,k+s[j],1);}
		else {for(int j=26,k=y-1;j;k+=s[j],j--)if(s[j])change(j,1,1,n,k+1,k+s[j],1);}
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=26;j++)
			if(query(j,1,1,n,i,i))printf("%c",j+96);
}
                

                
            
        
浙公网安备 33010602011771号