CF558E A Simple Task

题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过50000个操作。

每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序。

最后输出最终的字符串。

我扔:https://www.luogu.org/problemnew/show/CF558E

这题我们只需建26颗线段树维护区间覆盖,然后每次操作就把字母区间内的字母从小到大先提出来再插进去就行了,随便想想都能想到,就不多说了吧。

代码:

#include<bits/stdc++.h>
#define N 200005
using namespace std;
int sum[27][8*N], col[27][8*N], a[27][N];
void update1(int rt){
	for(int i = 0; i < 26; i ++) sum[i][rt] = sum[i][rt<<1] + sum[i][rt<<1|1];
}
void update(int rt, int o){//o表示第o个字母,下同
	sum[o][rt] = sum[o][rt<<1] + sum[o][rt<<1|1];
}
void build(int rt, int l, int r){ 
	if(l == r){
		for(int i = 0; i < 26; i ++) sum[i][rt] = a[i][l];
		return;
	}
	int mid = (l + r) >> 1;
	build(rt<<1, l, mid);
	build(rt<<1|1, mid + 1, r);
	update1(rt);
}
void pushdown(int rt, int l, int r, int o){//下放区间覆盖标记
	int mid = (l + r) >> 1;
	if(col[o][rt] == 1){
		col[o][rt<<1] = 1;
		col[o][rt<<1|1] = 1;
		sum[o][rt<<1] = mid - l + 1;
		sum[o][rt<<1|1] = r - mid;
		col[o][rt] = 0;
	}
	if(col[o][rt] == 2){
		col[o][rt<<1] = 2;
		col[o][rt<<1|1] = 2;
		sum[o][rt<<1] = 0;
		sum[o][rt<<1|1] = 0;
		col[o][rt] = 0;
	}
}
int query(int rt, int l, int r, int L, int R, int o){
	pushdown(rt, l, r, o);
	if(L <= l && r <= R){
		return sum[o][rt];
	}
	int mid = (l + r) >> 1, ret = 0;
	if(L <= mid) ret += query(rt<<1, l, mid, L, R, o);
	if(R > mid) ret += query(rt<<1|1, mid + 1, r, L, R, o);
	return ret;
}
void add(int rt, int l, int r, int L, int R, int o, int opt){
	pushdown(rt, l, r, o);
	if(L <= l && r <= R){
		if(opt == 1) col[o][rt] = 1, sum[o][rt] = r - l + 1;
		else col[o][rt] = 2, sum[o][rt] = 0;
		return;
	}
	int mid = (l + r) >> 1, ret = 0;
	if(L <= mid) add(rt<<1, l, mid, L, R, o, opt);
	if(R > mid) add(rt<<1|1, mid + 1, r, L, R, o, opt);
	update(rt, o);
}
void print(int rt, int l, int r){
	for(int i = 0; i < 26; i ++) pushdown(rt, l, r, i);
	if(l == r){
		for(int i = 0; i < 26; i ++){
			if(sum[i][rt]) {printf("%c", char(i + 'a'));break;}
		}
		return;
	}
	int mid = (l + r) >> 1;
	print(rt<<1, l, mid);
	print(rt<<1|1, mid + 1, r);
}
int n, m;
int main(){
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++){
		char ch;
		scanf(" %c", &ch);
		a[ch-'a'][i] = 1;
	}
	build(1, 1, n);
	for(;m --;){
		int l, r, k;
		scanf("%d%d%d", &l, &r, &k);
		if(k == 1){//升序
			int pos = l;
			for(int i = 0; i < 26; i ++){
				int t = query(1, 1, n, l, r, i);
				add(1, 1, n, l, r, i, 0);
				if(t) add(1, 1, n, pos, pos + t - 1, i, 1),	pos = pos + t;
			}
		}else{//降序
			int pos = l;
			for(int i = 26 - 1; i >= 0; i --){
				int t = query(1, 1, n, l, r, i);
				add(1, 1, n, l, r, i, 0);
				if(t) add(1, 1, n, pos, pos + t - 1, i, 1), pos = pos + t;
			}
		}
	}
	print(1, 1, n);
	return 0;
}
//emmmmmmm……还是挺简单的吧

1A!!!!

posted @ 2018-11-03 21:20  lahlah  阅读(24)  评论(0编辑  收藏  举报