思路:线段树维护字符串,翻转使用子段翻转,时间复杂度 O(26logN)
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int s[N*4],n,m,lzy[N*4],tr[N*4][26],f[26];
inline void pushup(int x){
for(int i=0;i<26;i++){
tr[x][i]=tr[x<<1][i]+tr[x<<1|1][i];//转移
}
return ;
}
inline void build(int k,int l,int r){//建线段树
if(l==r){
tr[k][s[l]]++;//某个节点上的字母数量
return ;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
inline void modify(int k,int l,int r){
if(!lzy[k]) return ;//懒标记
if(l==r) return ;
int mid=l+r>>1,s=mid-l+1;
if(lzy[k]==2){//偶数情况
for(int i=0;i<26;i++){
int x=min(tr[k][i],s);
tr[k<<1][i]=x;//翻转
tr[k][i]-=x;
s-=x;
}
}
else{//奇数情况
for(int i=25;i>=0;i--){
int x=min(tr[k][i],s);
tr[k<<1][i]=x;
tr[k][i]-=x;//翻转
s-=x;
}
}
for(int i=0;i<26;i++){
tr[k<<1|1][i]=tr[k][i];
tr[k][i]+=tr[k<<1][i];
}
lzy[k<<1|1]=lzy[k<<1]=lzy[k];
lzy[k]=0;
}
inline void getsum(int k,int l,int r,int s,int t){
if(l==s&&r==t){
for(int i=0;i<26;i++){
tr[0][i]+=tr[k][i];
tr[k][i]=0;
}
return ;
}
modify(k,l,r);
int mid=l+r>>1;
if(t<=mid) getsum(k<<1,l,mid,s,t);
else if (s>mid) getsum(k<<1|1,mid+1,r,s,t);
else{
getsum(k<<1,l,mid,s,mid);
getsum(k<<1|1,mid+1,r,mid+1,t);
}
}
inline void cover(int k,int l,int r,int s,int t,int p){
if(l==s&&r==t){
int s=r-l+1;
if(p==2){
for(int i=0;i<26;i++){//同上
int x=min(tr[0][i],s);
tr[k][i]=x;
tr[0][i]-=x;
s-=x;
}
}else{
for(int i=25;i>=0;i--){
int x=min(tr[0][i],s);
tr[k][i]=x;
tr[0][i]-=x;
s-=x;
}
}
lzy[k]=p;//标记已翻转
return ;
}
modify(k,l,r);
int mid=l+r>>1;//看与别的区间的交集
if(t<=mid) cover(k<<1,l,mid,s,t,p);
else if(s>mid) cover(k<<1|1,mid+1,r,s,t,p);
else{
cover(k<<1,l,mid,s,mid,p);
cover(k<<1|1,mid+1,r,mid+1,t,p);
}
pushup(k);
}
inline void findans(int k,int l,int r){//输出
if(l==r){
for(int i=0;i<26;i++){
if(tr[k][i]){
printf("%c",i+'a');
break;
}
}
return ;
}
if(lzy[k]) modify(k,l,r);
int mid=l+r>>1;
findans(k<<1,l,mid);
findans(k<<1|1,mid+1,r);
return ;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
char c;
cin>>c;
s[i]=c-'a';
}
build(1,1,n);
for(int i=1;i<=m;i++){
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
getsum(1,1,n,l,r);
cover(1,1,n,l,r,k+1);
// findans(1,1,n);
}
findans(1,1,n);
return 0;
}
完结撒花