CF558 E. A Simple Task

题目传送门:https://codeforces.com/problemset/problem/558/E

题目大意:
给定一串长度为\(n\)的小写字母串,有\(m\)个操作,每次操作将区间\([l_i,r_i]\)排序成非升(\(k_i=0\))或非降(\(k_i=1\))序列,输出问\(m\)次操作后的字符串


开26个线段树,每次将\([l_i,r_i]\)中所有的字符统计出来,然后再暴力按顺序插回去(区间覆盖)

每次询问是\(O(26\log^2n)\)的,插入也是\(O(26\log^2n)\)的,共计\(m\)组操作

最后询问的时间复杂度为\(O(26n\log n)\)

故总时间复杂度为\(O(26m\log^2n+26n\log n)\)(反正炸不了)

/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define ll_inf 1e18
#define MK make_pair
#define sqr(x) ((x)*(x))
#define pii pair<int,int>
#define int_inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
	int f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
template<typename T>inline T read(T x){
	int f=1; char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)	putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=1e5,K=26;
char s[N+10];
struct S1{
	#define ls (p<<1)
	#define rs (p<<1|1)
	int Tree[(N<<2)+10],Cov[(N<<2)+10];
	void update(int p){Tree[p]=Tree[ls]+Tree[rs];}
	void Add_Cov(int p,int l,int r,int v){
		Cov[p]=v;
		Tree[p]=(r-l+1)*v;
	}
	void pushdown(int p,int l,int r){
		if (!~Cov[p])	return;
		int mid=(l+r)>>1;
		Add_Cov(ls,l,mid,Cov[p]);
		Add_Cov(rs,mid+1,r,Cov[p]);
		Cov[p]=-1;
	}
	void Modify(int p,int l,int r,int L,int R,int v){
		if (L<=l&&r<=R){
			Add_Cov(p,l,r,v);
			return;
		}
		pushdown(p,l,r);
		int mid=(l+r)>>1;
		if (L<=mid)	Modify(ls,l,mid,L,R,v);
		if (R>mid)	Modify(rs,mid+1,r,L,R,v);
		update(p);
	}
	int Query(int p,int l,int r,int L,int R){
		if (L<=l&&r<=R)	return Tree[p];
		pushdown(p,l,r);
		int mid=(l+r)>>1,res=0;
		if (L<=mid)	res+=Query(ls,l,mid,L,R);
		if (R>mid)	res+=Query(rs,mid+1,r,L,R);
		return res;
	}
	#undef ls
	#undef rs
}ST[K];//Segment Tree
int Cnt[K];
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int n=read(0),m=read(0);
	scanf("%s",s+1);
	for (int i=1;i<=n;i++)	ST[s[i]-'a'].Modify(1,1,n,i,i,1);
	for (int i=1;i<=m;i++){
		int l=read(0),r=read(0),type=read(0);
		memset(Cnt,0,sizeof(Cnt));
		for (int k=0;k<K;k++){
			Cnt[k]+=ST[k].Query(1,1,n,l,r);
			ST[k].Modify(1,1,n,l,r,0);
		}
		int Last=l;
		if (type){	// non - decreasing
			for (int k=0;k<K;k++){
				if (!Cnt[k])	continue;
				ST[k].Modify(1,1,n,Last,Last+Cnt[k]-1,1);
				Last+=Cnt[k];
			}
		}else{
			for (int k=K-1;~k;k--){
				if (!Cnt[k])	continue;
				ST[k].Modify(1,1,n,Last,Last+Cnt[k]-1,1);
				Last+=Cnt[k];
			}
		}
	}
	for (int i=1;i<=n;i++)
		for (int k=0;k<K;k++)
			if (ST[k].Query(1,1,n,i,i))
				printf("%c",k+'a');
	return 0;
}
posted @ 2021-07-02 15:48  Wolfycz  阅读(36)  评论(0编辑  收藏  举报