string
【题目描述】
给定一个由小写字母组成的字符串 s。有 m 次操作,每次操作给
定 3 个参数 l,r,x。如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]
降序排序。你需要求出最终序列。
【输入数据】
第一行两个整数 n,m。第二行一个字符串 s。接下来 m 行每行三
个整数 x,l,r。
【输出数据】
一行一个字符串表示答案。
【样例输入】
5 2
cabcd
1 3 1
3 5 0
【样例输出】
abdcc
【数据范围】
对于 40%的数据,n,m<=1000。
对于 100%的数据,n,m<=100000。
题解:
正解不明,但可以写出nlogn*26*26的线段树(然而只比暴力多10分)。
看到一共只有26个字母,考虑枚举每个字母,统计在区间内部的个数,那么对于每种字母,显然如果按顺序排序,那么显然是从a~z,一个一个区间覆盖,区间清空。
线段树实现,当然lz打的是区间覆盖的标记,只要当前这个节点的元素值是什么,那么其他儿子节点的元素值就什么,就实现了区间清空和区间加法。
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define MAXN 110000 #define RG register using namespace std; struct node{ int lz,l,r,sum[26]; }a[MAXN*4]; int n,q; char ch[MAXN]; int chuan[MAXN],tot[26]; inline void pushup(int xv){ for(int i=0;i<=25;i++) a[xv].sum[i]=a[xv*2].sum[i]+a[xv*2+1].sum[i]; } inline void pushdown(int xv,int x,int y){ if(a[xv].lz){ a[xv].lz=0; for(int i=0;i<=25;i++){ if(a[xv].sum[i]==0) a[xv*2].sum[i]=a[xv*2+1].sum[i]=0; else a[xv*2].sum[i]=x,a[xv*2+1].sum[i]=y; } a[xv*2].lz=a[xv*2+1].lz=1; } } inline void build(int xv,int l,int r){ if(l==r){ a[xv].l=l,a[xv].r=r,a[xv].lz=0; memset(a[xv].sum,0,sizeof(a[xv].sum)); a[xv].sum[chuan[l]]=1; return; } a[xv].l=l,a[xv].r=r; int mid=(l+r)/2; build(xv*2,l,mid),build(xv*2+1,mid+1,r); pushup(xv); } inline int query(int xv,int l,int r,int k){ RG int L=a[xv].l,R=a[xv].r,mid=(L+R)/2; if(L==l&&R==r){ return a[xv].sum[k]; } pushdown(xv,mid-L+1,R-mid); if(r<=mid) return query(xv*2,l,r,k); else if(l>mid) return query(xv*2+1,l,r,k); else return query(xv*2,l,mid,k)+query(xv*2+1,mid+1,r,k); } inline void update(int xv,int l,int r,int k){ RG int L=a[xv].l,R=a[xv].r,mid=(L+R)/2; if(l==L&&R==r){ memset(a[xv].sum,0,sizeof(a[xv].sum)); a[xv].sum[k]=r-l+1; a[xv].lz=1; return; } pushdown(xv,mid-L+1,R-mid); if(r<=mid) update(xv*2,l,r,k); else if(l>mid) update(xv*2+1,l,r,k); else update(xv*2,l,mid,k),update(xv*2+1,mid+1,r,k); pushup(xv); } inline int query2(int xv,int ps){ RG int L=a[xv].l,R=a[xv].r,mid=(L+R)/2; if(L==R){ for(int i=0;i<=25;i++) if(a[xv].sum[i]) return i; } pushdown(xv,mid-L+1,R-mid); if(ps<=mid) return query2(xv*2,ps); else return query2(xv*2+1,ps); } int main() { scanf("%d%d",&n,&q); scanf("%s",ch+1); for(int i=1;i<=n;i++) chuan[i]=ch[i]-'a'; build(1,1,n); while(q--){ int l,r,x;scanf("%d%d%d",&l,&r,&x); if(l>r) swap(l,r); memset(tot,0,sizeof(tot)); for(int i=0;i<=25;i++) tot[i]+=query(1,l,r,i); if(x==1){ int ll=l,rr=l-1; for(int i=0;i<=25;i++){ if(tot[i]!=0){ rr+=tot[i]; update(1,ll,rr,i); ll=rr+1; } } } else{ int ll=l,rr=l-1; for(int i=25;i>=0;i--){ if(tot[i]!=0){ rr+=tot[i]; update(1,ll,rr,i); ll=rr+1; } } } } for(int i=1;i<=n;i++){ printf("%c",query2(1,i)+'a'); } return 0; }