CodeForces 558E(计数排序+线段树优化)

时间:2023-03-09 08:22:48
CodeForces 558E(计数排序+线段树优化)

题意:一个长度为n的字符串(只包含26个小字母)有q次操作 对于每次操作 给一个区间 和k k为1把该区间的字符不降序排序 k为0把该区间的字符不升序排序 求q次操作后所得字符串

思路:

该题数据规模很大 排序是关键想到计数排序,根据计数排序原理,由只有26个小写字母,需要统计区间字母的个数,还需要更新区间,想到用线段树优化,对于每个字母建一个线段树维护各字母在区间的个数。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<1|1
#define All 1,N,1
#define N 100010
#define read freopen("in.txt", "r", stdin)
const ll INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod = 1000000007;
struct tree{
int num,l,r,lazy;
}t[30][N<<2];
int qnum[N],n,q;
char ch[N];
void pushup(int i,int rt){
t[i][rt].num=t[i][rt<<1].num+t[i][rt<<1|1].num;
}
void pushdown(int i,int rt){
if(t[i][rt].lazy!=-1){
t[i][rt<<1].num=(t[i][rt<<1].r-t[i][rt<<1].l+1)*t[i][rt].lazy;
t[i][rt<<1].lazy=t[i][rt].lazy;
t[i][rt<<1|1].num=(t[i][rt<<1|1].r-t[i][rt<<1|1].l+1)*t[i][rt].lazy;
t[i][rt<<1|1].lazy=t[i][rt].lazy;
t[i][rt].lazy=-1;
}
}
void build(int i,int l,int r,int rt){
t[i][rt].l=l;
t[i][rt].r=r;
t[i][rt].lazy=-1;
int m=(l+r)>>1;
if(l==r){
t[i][rt].num=(ch[l-1]=='a'+i);
return;
}
build(i,lson);
build(i,rson);
pushup(i,rt);
}
void update(int i,int v,int l,int r,int rt){
if(t[i][rt].l>=l&&t[i][rt].r<=r){
t[i][rt].num=(t[i][rt].r-t[i][rt].l+1)*v;
t[i][rt].lazy=v;
return;
}
pushdown(i,rt);
int m=(t[i][rt].l+t[i][rt].r)>>1;
if(l<=m)update(i,v,l,r,rt<<1);
if(r>m)update(i,v,l,r,rt<<1|1);
pushup(i,rt);
}
int query(int i,int l,int r,int rt){
if(t[i][rt].l>=l&&t[i][rt].r<=r)
return t[i][rt].num;
pushdown(i,rt);
int total=0;
int mid=(t[i][rt].l+t[i][rt].r)>>1;
if(l<=mid)total+=query(i,l,r,rt<<1);
if(r>mid)total+=query(i,l,r,rt<<1|1);
pushup(i,rt);
return total;
}
void solve(){
int l,r,w;
for(int i=0;i<26;++i)
build(i,1,n,1);
while(q--){
scanf("%d%d%d",&l,&r,&w);
for(int i=0;i<26;++i){
qnum[i]=query(i,l,r,1);
update(i,0,l,r,1);
}
if(w==1){
int pos=l;
for(int i=0;i<26;++i)
{
if(qnum[i]>0){
update(i,1,pos,pos+qnum[i]-1,1);
pos+=qnum[i];
}
}
}
else{
int pos=l;
for(int i=25;i>=0;--i)
{
if(qnum[i]>0){
update(i,1,pos,pos+qnum[i]-1,1);
pos+=qnum[i];
}
}
}
}
for(int i=0;i<n;++i)
for(int j=0;j<26;++j)
{
if(query(j,i+1,i+1,1)){
ch[i]='a'+j;
break;
}
}
printf("%s\n",ch);
}
int main()
{
scanf("%d%d",&n,&q);
scanf("%s",ch);
solve();
return 0;
}