CF558E-A Simple Task

题目

开始给出一个长度为\(n\)的小写字母串,\(m\)次操作,每次选一个区间,把这个区间进行升序或降序排序。最后输出所有操作结束后的串。

\(n\le 10^5,m\le 5\times 10^4\)

分析

神思路!!

其实主要是要注意到这个字母表为26非常小,所以可以考虑使用基数排序!事实上排序也可以看成统计每种数有多少个按顺序输出的过程。

二十六颗线段树,维护区间中每种字母的出现次数。排序的时候遍历所有的字母,把该排在前面的全部移到前面。这可以用一个支持区间求和,区间加法,区间清零的线段树来做,写的时候标记可以用一个二元组来表示,\(x=a_0*x+a_1*len\)

总而言之用每个字母的位置来刻画这个序列。

其实很多字符串问题都是基于字母表比较小来做的。

代码

#include<cstdio>
#include<cctype>
#include<cstring>
#include<utility>
#include<algorithm>
using namespace std;
int read() {
	int x=0,f=1;
	char c=getchar();
	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
const int maxn=1e5+1;
const int maxc=26;
int n,m;
char s[maxn];
pair<int,int> operator + (pair<int,int> a,pair<int,int> b) {
	return make_pair(a.first*b.first,a.second*b.first+b.second);
}
struct SGT {
	int t[maxn<<2];
	pair<int,int> tag[maxn<<2];
	void build(int x,int l,int r) {
		if (l==r) return;
		t[x]=0,tag[x]=make_pair(1,0);
		int mid=(l+r)>>1;
		build(x<<1,l,mid),build(x<<1|1,mid+1,r);
	}
	void doit(int x,int l,int r,pair<int,int> d) {
		t[x]=t[x]*d.first+(r-l+1)*d.second;
		tag[x]=tag[x]+d;
	}
	void pushdown(int x,int l,int mid,int r) {
		doit(x<<1,l,mid,tag[x]);
		doit(x<<1|1,mid+1,r,tag[x]);
		tag[x]=make_pair(1,0);
	}
	void modify(int x,int L,int R,int l,int r,pair<int,int> d) {
		if (L==l && R==r) {
			doit(x,L,R,d);
			return;
		}
		int mid=(L+R)>>1;
		pushdown(x,L,mid,R);
		if (r<=mid) modify(x<<1,L,mid,l,r,d); else 
		if (l>mid) modify(x<<1|1,mid+1,R,l,r,d); else
		modify(x<<1,L,mid,l,mid,d),modify(x<<1|1,mid+1,R,mid+1,r,d);
		t[x]=t[x<<1]+t[x<<1|1];
	}
	void clear(int l,int r) {
		if (l>r) return;
		modify(1,1,n,l,r,make_pair(0,0));
	}
	void inc(int l,int r) {
		if (l>r) return;
		modify(1,1,n,l,r,make_pair(1,1));
	}
	int query(int x,int L,int R,int l,int r) {
		if (L==l && R==r) return t[x];
		int mid=(L+R)>>1;
		pushdown(x,L,mid,R);
		if (r<=mid) return query(x<<1,L,mid,l,r);
		if (l>mid) return query(x<<1|1,mid+1,R,l,r);
		return query(x<<1,L,mid,l,mid)+query(x<<1|1,mid+1,R,mid+1,r);
	}
	int query(int l,int r) {
		if (l>r) return 0;
		return query(1,1,n,l,r);
	}
} sgt[maxc];
int main() {
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
#endif
	n=read(),m=read();
	scanf("%s",s+1);
	for (int i=0;i<maxc;++i) sgt[i].build(1,1,n);
	for (int i=1;i<=n;++i) sgt[s[i]-'a'].inc(i,i);
	while (m--) {
		int l=read(),r=read(),o=read();
		if (o) {
			int alr=0;
			for (int i=0;i<maxc;++i) {
				int tmp=sgt[i].query(l,r);
				sgt[i].clear(l,r);
				sgt[i].inc(l+alr,l+alr+tmp-1);
				alr+=tmp;
			}
		} else {
			int alr=0;
			for (int i=maxc-1;i>=0;--i) {
				int tmp=sgt[i].query(l,r);
				sgt[i].clear(l,r);
				sgt[i].inc(l+alr,l+alr+tmp-1);
				alr+=tmp;
			}
		}
	}
	for (int i=1,j;i<=n;++i) {
		for (j=0;j<maxc;++j) if (sgt[j].query(i,i)) {
			putchar('a'+j);
			break;
		}
	}
	puts("");
	return 0;
}
posted @ 2017-07-12 15:11  permui  阅读(178)  评论(0编辑  收藏  举报