Codeforces 558E A Simple Task (计数排序+线段树优化)
来源:互联网 发布:java数据库编程题型 编辑:程序博客网 时间:2024/05/22 07:52
This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.
Output the final string after applying the queries.
The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively.
Next line contains a string S itself. It contains only lowercase English letters.
Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, ).
Output one line, the string S after applying the queries.
10 5abacdabcda7 10 05 8 11 4 03 6 07 10 1
cbcaaaabdd
10 1agjucbvdfk1 10 1
abcdfgjkuv
First sample test explanation:
题意:
给定一个长度为n的字符串,有q次操作,每次操作将一个区间内的字符按升序或降序排列,输出q次操作后的字符串,串中只包含小写英文字母.
分析:
考虑到字符集大小只有26,联想到计数排序,对一个区间做一次排序相当于对区间内每一种字符分别统计一遍个数后,再按照字符的顺序(升序或降序)依次重新填进区间内,可以用26棵权值线段树分别维护每一种字符的位置,复杂度O(26nlogn+52qlogn)。
代码:
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;const int MAXN=100005;int cnt[26];char str[MAXN],ans[MAXN];struct node{ int l,r,m,v,lazy;}s[26][MAXN<<2];void push_up(int n,int id){ s[id][n].v=s[id][n<<1].v+s[id][n<<1|1].v;}void push_down(int n,int id){ if(s[id][n].lazy<0)return; s[id][n<<1].v=(s[id][n<<1].r-s[id][n<<1].l)*s[id][n].lazy; s[id][n<<1].lazy=s[id][n].lazy; s[id][n<<1|1].v=(s[id][n<<1|1].r-s[id][n<<1|1].l)*s[id][n].lazy; s[id][n<<1|1].lazy=s[id][n].lazy; s[id][n].lazy=-1;}void build(int l,int r,int n,int id){ int m=(l+r)>>1; s[id][n].l=l; s[id][n].r=r; s[id][n].m=m; s[id][n].lazy=-1; if(r-l==1) { s[id][n].v=(str[l-1]=='a'+id); return; } build(l,m,n<<1,id); build(m,r,n<<1|1,id); push_up(n,id);}void update(int l,int r,int n,int op,int id){ if(s[id][n].l==l && s[id][n].r==r) { s[id][n].v=(s[id][n].r-s[id][n].l)*op; s[id][n].lazy=op; return; } push_down(n,id); if(r<=s[id][n].m)update(l,r,n<<1,op,id); else if(l>=s[id][n].m)update(l,r,n<<1|1,op,id); else { update(l,s[id][n].m,n<<1,op,id); update(s[id][n].m,r,n<<1|1,op,id); } push_up(n,id);}int query(int l,int r,int n,int id){ if(s[id][n].l==l && s[id][n].r==r) return s[id][n].v; push_down(n,id); if(r<=s[id][n].m) return query(l,r,n<<1,id); if(l>=s[id][n].m) return query(l,r,n<<1|1,id); return query(l,s[id][n].m,n<<1,id) +query(s[id][n].m,r,n<<1|1,id);}int main(){ int n,q; scanf("%d%d",&n,&q); scanf("%s",str); for(int i=0;i<26;i++)build(1,n+1,1,i); int l,r,k; while(q--) { scanf("%d%d%d",&l,&r,&k); for(int i=0;i<26;i++) { cnt[i]=query(l,r+1,1,i); update(l,r+1,1,0,i); } if(k==1) { int loc=l; for(int i=0;i<26;i++) { if(cnt[i]>0)update(loc,loc+cnt[i],1,1,i); loc+=cnt[i]; } } else { int loc=l; for(int i=25;i>=0;i--) { if(cnt[i]>0)update(loc,loc+cnt[i],1,1,i); loc+=cnt[i]; } } } for(int i=1;i<=n;i++) for(int j=0;j<26;j++) if(query(i,i+1,1,j)) { ans[i-1]='a'+j; break; } printf("%s\n",ans); return 0;}
- Codeforces 558E. A Simple Task (线段树+计数排序)
- Codeforces 558E A Simple Task (计数排序+线段树优化)
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
- [计数排序 线段树] Codeforces 558E #312 (Div. 2) E. A Simple Task
- CF 558E(A Simple Task-计数排序+线段树)
- cf #312 E. A Simple Task (线段树+计数排序)
- 字符串q次操作将(l,r)内的字符升序或降序排列 计数排序 + 线段树优化 Codeforces div2 558E A Simple Task
- codeforces 558E E. A Simple Task( 线段树+统计排序)
- codeforces 558E A Simple Task 线段树
- [线段树] codeforces 558E. A Simple Task
- cf#312-E-A Simple Task- 线段树+暴力(计数排序)
- A Simple Task(Codeforces Round #312 (Div. 2) 线段树+计数排序)
- Codeforces 558E A Simple Task(线段树区间更新)
- Codeforces 558E A Simple Task 线段树(区间更新)
- CF 558E A Simple Task(多维线段树)
- CF 558E A Simple Task (线段树)
- codeforces 558 E A Simple Task
- 【30.93%】【codeforces 558E】A Simple Task
- “程序员”学哪种编程语言最赚钱?
- Git命令大全
- Unity3d-反编译C#和提取资源
- SQLDMO注册
- JAXB中的标注
- Codeforces 558E A Simple Task (计数排序+线段树优化)
- 暂时在heap上留个坑
- poj3281
- ATL结构分析
- GRE写作必备句型
- 如何启动Tomcat服务器
- Android使用反射机制设置ListView的默认焦点
- Decode Ways
- hudson插件介绍