题意:一个长度为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; }