隐藏
「雅礼day3」字符串string - 线段树模拟 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「雅礼day3」字符串string - 线段树模拟

题目大意

给定一个由小写字母组成的字符串 s。有 m 次操作,每次操作给定 3 个参数 l,r,x。如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]降序排序。你需要求出最终序列。


题目分析

因为字符集大小$26$是一个常数,因此我们可以暴力查询区间中字符集的出现数量,然后暴力重置区间。

用线段树维护一下区间查询和区间修改即可。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=100005;
char s[maxn];
struct Tree {
int left,right,sum[26],lazy;
Tree(int l=0,int r=0,int la=-1):left(l),right(r),lazy(la) {
memset(sum,0,sizeof(sum));
}
};
struct Segment_Tree {
Tree tree[maxn*4];
#define ls index<<1
#define rs index<<1|1
void build(int index,int Left,int Right) {
tree[index]=Tree(Left,Right);
if(Left==Right) {
tree[index].sum[s[Left-1]-'a']++;
return;
}
int mid=(Left+Right)>>1;
build(ls,Left,mid);
build(rs,mid+1,Right);
push_up(index);
}
void push_up(int index) {
for(int i=0; i<26; i++)tree[index].sum[i]=tree[ls].sum[i]+tree[rs].sum[i];
}
void push_down(int index) {
if(tree[index].lazy==-1)return;
fill(tree[ls].sum,tree[ls].sum+26,0);
fill(tree[rs].sum,tree[rs].sum+26,0);
tree[ls].lazy=tree[rs].lazy=tree[index].lazy;
tree[ls].sum[tree[index].lazy]=tree[ls].right-tree[ls].left+1;
tree[rs].sum[tree[index].lazy]=tree[rs].right-tree[rs].left+1;
tree[index].lazy=-1;
}
void modify(int index,int Left,int Right,int v) {
if(Right<tree[index].left||Left>tree[index].right)return;
if(Left<=tree[index].left&&Right>=tree[index].right) {
fill(tree[index].sum,tree[index].sum+26,0);
tree[index].sum[v]=tree[index].right-tree[index].left+1;
tree[index].lazy=v;
return;
}
push_down(index);
modify(ls,Left,Right,v);
modify(rs,Left,Right,v);
push_up(index);
}
void query(int index,int Left,int Right,int* ans) {
if(Right<tree[index].left||Left>tree[index].right)return;
if(Left<=tree[index].left&&Right>=tree[index].right) {
for(int i=0; i<26; i++)ans[i]+=tree[index].sum[i];
return;
}
push_down(index);
query(ls,Left,Right,ans);
query(rs,Left,Right,ans);
}
void sort(int Left,int Right,int bj) {
static int sum[26];
fill(sum,sum+26,0);
query(1,Left,Right,sum);
if(bj) {
for(int i=0; i<26; i++) {
if(!sum[i])continue;
modify(1,Left,Left+sum[i]-1,i);
Left+=sum[i];
}
} else {
for(int i=25; i>=0; i--) {
if(!sum[i])continue;
modify(1,Left,Left+sum[i]-1,i);
Left+=sum[i];
}
}
}
void Output(int index) {
if(tree[index].left==tree[index].right) {
for(int i=0; i<26; i++)
if(tree[index].sum[i])putchar(i+'a');
return;
}
push_down(index);
Output(ls);
Output(rs);
}
} st;
int n,m;
int main() {
n=Get_Int();
m=Get_Int();
scanf("%s",s);
st.build(1,1,n);
for(int i=1; i<=m; i++) {
int l=Get_Int(),r=Get_Int(),opt=Get_Int();
st.sort(l,r,opt);
}
st.Output(1);
return 0;
}
姥爷们赏瓶冰阔落吧~