( ext{Descrption})
题目描述
给定一个仅由小写字母组成的字符串s。
有m次操作,每次操作有3个参数L,R,opt。
如果opt为1,那么将区间[L,R]内的字符按升序(即从'a'到'z')排列。
如果opt为0,那么将区间[L,R]内的字符按降序(即从'z'到'a')排列。
求m次操作后的字符串。
输入格式
第一行两个正整数 n 和 m,分别表示字符串的长度和操作次数。
接下来一行一个长度为 n 的字符串。
接下来 m 行每行 3 个正整数 L,R,opt_i,表示一个操作。
输出格式
输出一行一个长度为n的字符串,表示m次操作后的字符串。
样例输入
5 2
cabcd
1 3 1
3 5 0
样例输出
abdcc
数据规模与约定
对于 40% 的数据, 1≤n≤1000 , 0≤m≤1000 。
对于 100% 的数据, 1≤n≤10^5 , 0≤m≤10^5 , 0≤opt≤1 , 1≤L≤R≤n 。
( ext{Solution})
感觉很神奇。
其实关键就是这里的权值只有 (26) 种。
我们可以从小到大枚举字母分界线 (ch),大于等于 (ch) 的字母赋为 (1),反之为 (0)。然后依次进行 (m) 次排序(以 (0,1) 为关键字),然后我们可以 (mathcal O(log n)) 地查询某个位置是否大于等于 (ch),如果是就先赋为 (ch),这样下一次当前的 (ch) 变成 (0),不会再被赋值,后面的字母也能被赋值。
( ext{Code})
#include <cstdio>
#define rep(i,_l,_r) for(signed i=(_l),_end=(_r);i<=_end;++i)
#define print(x,y) write(x),putchar(y)
int read() {
int x=0,f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
void write(int x) {
if(x<0) return (void)(putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
const int maxn=1e5+5;
int n,m,L[maxn],R[maxn],op[maxn],t[maxn<<2];
char s[maxn],ans[maxn];
void pushDown(int o,int l,int r) {
int mid=l+r>>1;
if(t[o]==r-l+1) t[o<<1]=mid-l+1,t[o<<1|1]=r-mid;
else if(t[o]==0) t[o<<1]=t[o<<1|1]=0;
}
void modify(int o,int l,int r,int L,int R,int k) {
if(l>R||r<L) return;
if(l>=L&&r<=R) {t[o]=k*(r-l+1); return;}
int mid=l+r>>1;
pushDown(o,l,r);
modify(o<<1,l,mid,L,R,k); modify(o<<1|1,mid+1,r,L,R,k);
t[o]=t[o<<1]+t[o<<1|1];
}
int query(int o,int l,int r,int L,int R) {
if(l>R||r<L) return 0;
if(l>=L&&r<=R) return t[o];
int mid=l+r>>1;
pushDown(o,l,r);
return query(o<<1,l,mid,L,R)+query(o<<1|1,mid+1,r,L,R);
}
void work() {
rep(i,1,m) {
int cnt=query(1,1,n,L[i],R[i]);
if(cnt==R[i]-L[i]+1||cnt==0) continue;
if(op[i]) modify(1,1,n,L[i],R[i]-cnt,0),modify(1,1,n,R[i]-cnt+1,R[i],1);
else modify(1,1,n,L[i],L[i]+cnt-1,1),modify(1,1,n,L[i]+cnt,R[i],0);
}
}
int main() {
n=read(),m=read();
scanf("%s",s+1);
rep(i,1,m) L[i]=read(),R[i]=read(),op[i]=read();
for(char ch='a';ch<='z';++ch) {
rep(i,1,n) modify(1,1,n,i,i,s[i]>=ch);
work();
rep(i,1,n) if(query(1,1,n,i,i)) ans[i]=ch;
}
rep(i,1,n) putchar(ans[i]); puts("");
return 0;
}