Codeforces 558E A Simple Task(线段树区间更新)
来源:互联网 发布:招聘软件排名 编辑:程序博客网 时间:2024/05/29 18:18
题意:
给定一个长度为n的字符串,有q次操作,每次操作将一个区间内的字符按升序或降序排列,输出q次操作后的字符串,串中只包含小写英文字母.
解析:
考虑到字符集大小只有26,联想到计数排序,对一个区间做一次排序相当于对区间内每一种字符分别统计一遍个数后,再按照字符的顺序(升序或降序)依次重新填进区间内,可以用26棵权值线段树分别维护每一种字符的位置,复杂度
O(26nlog2(n)+52qlog2(n)) 。
#include <cstdio>#include <cstring>#include <algorithm>#include <cstdlib>#define ls (o<<1)#define rs (o<<1|1)#define lson ls,L,M#define rson rs,M+1,Rusing namespace std;typedef long long ll;const int N = 100005;const int sigma = 26;int sumv[N<<2][sigma], setv[N<<2]; //setv表示当前区间被覆盖的字母int cnt[26]; //每个坐标在当前区间出现的次数char str[N];void pushUp(int o) { for(int i = 0; i < sigma; i++) { sumv[o][i] = sumv[ls][i] + sumv[rs][i]; }}void initNode(int o) { memset(sumv[o], 0, sizeof(sumv[o]));}void pushDown(int o, int L, int R) { int M = (L+R)/2; if(setv[o] != -1) { setv[ls] = setv[rs] = setv[o]; initNode(ls); sumv[ls][setv[o]] = (M-L+1); initNode(rs); sumv[rs][setv[o]] = (R-M); setv[o] = -1; }}void build(int o, int L, int R) { if(L == R) { initNode(o); sumv[o][str[L]-'a'] = 1; setv[o] = str[L]-'a'; return ; } setv[o] = -1; int M = (L+R)/2; build(lson); build(rson); pushUp(o);}int query(int o, int L, int R, int ql, int qr, int val) { if(ql <= L && R <= qr) return sumv[o][val]; pushDown(o, L, R); int M = (L+R)/2, ret = 0; if(ql <= M) ret += query(lson, ql, qr, val); if(qr > M) ret += query(rson, ql, qr, val); return ret;}void modify(int o, int L, int R, int ql, int qr, int val) { if(ql <= L && R <= qr) { for(int i = 0; i < sigma; i++) sumv[o][i] = 0; setv[o] = val; sumv[o][setv[o]] = (R-L+1); return ; } pushDown(o, L, R); int M = (L+R)/2; if(ql <= M) modify(lson, ql, qr, val); if(qr > M) modify(rson, ql, qr, val); pushUp(o);}void getStr(int o, int L, int R) { if(L == R) { printf("%c", (char)('a'+setv[o])); return ; } pushDown(o, L, R); int M = (L+R)/2; getStr(lson); getStr(rson);}int n, q;int main() { while(scanf("%d%d", &n, &q) != EOF) { scanf("%s", str+1); build(1, 1, n); int ql, qr, ch; while(q--) { scanf("%d%d%d", &ql, &qr, &ch); for(int i = 0; i < sigma; i++) cnt[i] = query(1, 1, n, ql, qr, i); int pos = ql; if(ch == 1) { for(int i = 0; i < sigma; i++) { if(cnt[i] > 0) modify(1, 1, n, pos, pos+cnt[i]-1, i); pos += cnt[i]; } }else { for(int i = sigma-1; i >= 0; i--) { if(cnt[i] > 0) modify(1, 1, n, pos, pos+cnt[i]-1, i); pos += cnt[i]; } } } getStr(1, 1, n); puts(""); } return 0;}
0 0
- Codeforces 558E A Simple Task(线段树区间更新)
- Codeforces 558E A Simple Task 线段树(区间更新)
- codeforces 558E A Simple Task 线段树
- Codeforces 558E. A Simple Task (线段树+计数排序)
- [线段树] codeforces 558E. A Simple Task
- CF 558E A Simple Task(多维线段树)
- CF 558E A Simple Task (线段树)
- codeforces 558E E. A Simple Task( 线段树+统计排序)
- [计数排序 线段树] Codeforces 558E #312 (Div. 2) E. A Simple Task
- Codeforces 558E A Simple Task (计数排序+线段树优化)
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
- Codeforces Round #312 (Div. 2) E. A Simple Task 线段树(未敲)
- CF 558E(A Simple Task-计数排序+线段树)
- codeforces 558 E A Simple Task
- 【30.93%】【codeforces 558E】A Simple Task
- Codeforces Round #312 (Div. 2) E. A Simple Task 线段树 延时标记
- Codeforces Round #312 (Div. 2) E A Simple Task 线段树
- A Simple Problem with Integers (线段树区间更新)
- 【Android】检测是否处于Wifi环境,利用WebView实现浏览器app
- PTAM算法流程介绍
- Cantor的数表,注意一些题中数学的应用
- 正则表达式常用元字符
- IOS开发系列--IOS程序开发概览(翻译自Kenshin Cui's Blog)
- Codeforces 558E A Simple Task(线段树区间更新)
- 添加php扩展 此博文包含图片(2014-04-24 16:22:49)
- redis时间事件
- eclipse Package Explorer视图设置过滤功能
- iOS中 imageNamed方法 很多图片占用大量内存问题
- 【直播预告】7月18日3D游戏引擎免费公开课答疑,参与送C币!
- Vimdiff的用法
- YT05-动态归划求解课后题目-1004—Max Sum -(6.21日-烟台大学ACM预备队解题报告)
- Java泛型,结合JSONObject动态生成指定的对象