题意:
给定一个长度不超过10^5的字符串和不超过m次操作。
每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序。
最后输出最终的字符串。
做法:线段树
思路:
根据计数排序的原理,只要知道了有几个数比t小,就可以知道t的位置
这道题只有26个字母,我们只需建26颗线段树
在每次操作时,首先求出这个区间中a~z每个数出现的次数
再分别对每一位字母进行区间覆盖。
对下一个区间进行覆盖要加上之前覆盖的长度
如果是升序排序,我们从a到z依次查询所有线段树,降序就从z到a依次查询
最后遍历整棵线段树输出最终的字符串
代码
#include <bits/stdc++.h> using namespace std; #define pb push_back #define mp(aa,bb) make_pair(aa,bb) #define _for(i,b) for(int i=(0);i<(b);i++) #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define per(i,b,a) for(int i=(b);i>=(a);i--) #define mst(abc,bca) memset(abc,bca,sizeof abc) #define X first #define Y second #define lowbit(a) (a&(-a)) #define debug(a) cout<<#a<<":"<<a<<"\n" typedef long long ll; typedef pair<int,int> pii; typedef unsigned long long ull; typedef long double ld; const int N=100010; const int INF=0x3f3f3f3f; const int mod=1e9+7; const double eps=1e-6; const double PI=acos(-1.0); struct Tree{ bool tag[26]; int w[26]; int l,r; }tree[N<<2]; struct node{ int v[26]; }zero; int a[N]; void pushup(int u){ rep(i,0,25) tree[u].w[i]=tree[u<<1].w[i]+tree[u<<1|1].w[i]; } void pushdown(int u){ if(tree[u].l==tree[u].r){ return; } rep(i,0,25){ if(tree[u].tag[i]){ rep(j,0,25){ tree[u<<1].tag[j]=0; tree[u<<1].w[j]=0; tree[u<<1|1].tag[j]=0; tree[u<<1|1].w[j]=0; } tree[u<<1].tag[i]=1; tree[u<<1|1].tag[i]=1; tree[u<<1].w[i]=tree[u<<1].r-tree[u<<1].l+1; tree[u<<1|1].w[i]=tree[u<<1|1].r-tree[u<<1|1].l+1; tree[u].tag[i]=0; } } } void build(int l,int r,int u){ tree[u].l=l,tree[u].r=r; if(l==r){ tree[u].w[a[l]]=1; return; } int mid=(l+r)>>1; build(l,mid,u<<1); build(mid+1,r,u<<1|1); pushup(u); } void update(int l,int r,int v,int u){ if(tree[u].l>r||tree[u].r<l){ return; } if(l<=tree[u].l&&r>=tree[u].r){ rep(i,0,25){ tree[u].w[i]=0; tree[u].tag[i]=0; } tree[u].tag[v]=1; tree[u].w[v]=tree[u].r-tree[u].l+1; return; } pushdown(u); int mid=(tree[u].l+tree[u].r)>>1; if(l<=mid) update(l,r,v,u<<1); if(r>mid) update(l,r,v,u<<1|1); pushup(u); } node query(int l,int r,int u){ if(l<=tree[u].l&&r>=tree[u].r){ node t; rep(i,0,25){ t.v[i]=tree[u].w[i]; } return t; } pushdown(u); int mid=(tree[u].l+tree[u].r)>>1; node t=zero; if(l<=mid){ node tt=query(l,r,u<<1); rep(i,0,25){ t.v[i]+=tt.v[i]; } } if(r>mid){ node tt=query(l,r,u<<1|1); rep(i,0,25){ t.v[i]+=tt.v[i]; } } return t; } void print(int u){ pushdown(u); if(tree[u].l==tree[u].r){ rep(i,0,25){ if(tree[u].w[i]){ cout<<(char)('a'+i); return; } } } print(u<<1); print(u<<1|1); } void solve(){ int n,m;cin>>n>>m; rep(i,1,n){ char x;cin>>x; a[i]=x-'a'; } build(1,n,1); while(m--){ int l,r,op;cin>>l>>r>>op; node t=query(l,r,1); if(op){ //升序 rep(i,0,25){ update(l,l+t.v[i]-1,i,1); l+=t.v[i]; } } else{ //降序 per(i,25,0){ update(l,l+t.v[i]-1,i,1); l+=t.v[i]; } } } print(1); } int main(){ ios::sync_with_stdio(0);cin.tie(0); // int t;cin>>t;while(t--) solve(); return 0; }