我是靠谱客的博主 优秀母鸡,这篇文章主要介绍12.CF558E A Simple Task 线段树维护字符串区间排序12.CF558E A Simple Task 线段树维护字符串区间排序,现在分享给大家,希望可以做个参考。

12.CF558E A Simple Task 线段树维护字符串区间排序

个人Limitの线段树题单题解主目录:Limitの线段树题单 题解目录_HeartFireY的博客-CSDN博客

要求对于给定的字符串,对给定的区间进行排序

线段树经典应用,维护26棵线段树,实现区间覆盖和查询即可。

洛谷传送门:CF558E A Simple Task - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

CF传送门:E. A Simple Task (codeforces.com)

题目分析

要求对于给定的字符串,对给定的区间进行排序。

我们维护 26 26 26棵线段树,每颗线段树上记录对应字母所在的位置(叶节点 0 − 1 0-1 01表示有没有,然后维护区间和表示区间字母个数)。对于区间排序,我们只需要取出区间在 26 26 26棵线段树上的信息,然后按照升序或降序覆盖即可。

因为要维护区间覆盖,因此也需要打 L a z y Lazy Lazy标记。

Code

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <bits/stdc++.h> #pragma gcc optimize("O2") #pragma g++ optimize("O2") #define int long long #define endl 'n' using namespace std; const int N = 2e2 + 10, MOD = 1e9 + 7; string s; char ans[N]; namespace SegTree{ #define ls rt << 1 #define rs rt << 1 | 1 #define lson ls, id, l, mid #define rson rs, id, mid + 1, r int tree[N << 2][26], lazy[N << 2][26]; inline void push_up(int rt, int id){ tree[rt][id] = tree[ls][id] + tree[rs][id]; } inline void push_down(int rt, int id, int m){ if(lazy[rt][id] == -1) return; lazy[ls][id] = lazy[rs][id] = lazy[rt][id]; tree[ls][id] = lazy[rt][id] * (m - (m >> 1)); tree[rs][id] = lazy[rt][id] * (m >> 1); lazy[rt][id] = -1; } void build(int rt, int id, int l, int r){ lazy[rt][id] = -1, tree[rt][id] = 0; if(l == r){ tree[rt][id] += (s[l] - 'a' == id); return; } int mid = l + r >> 1; build(lson), build(rson); push_up(rt, id); } void update(int rt, int id, int l, int r, int L, int R, int val){ if(l >= L && r <= R){ tree[rt][id] = val * (r - l + 1); lazy[rt][id] = val; return; } push_down(rt, id, r - l + 1); int mid = l + r >> 1; if(mid >= L) update(lson, L, R, val); if(mid < R) update(rson, L, R, val); push_up(rt, id); } int query(int rt, int id, int l, int r, int L, int R){ if(l >= L && r <= R) return tree[rt][id]; push_down(rt, id, r - l + 1); int mid = l + r >> 1, ans = 0; if(mid >= L) ans += query(lson, L, R); if(mid < R) ans += query(rson, L, R); return ans; } void getans(int rt, int id, int l, int r){ if(l == r){ if(tree[rt][id]) ans[l] = (char)('a' + id); return; } push_down(rt, id, r - l + 1); int mid = l + r >> 1; getans(lson), getans(rson); } } inline void solve(){ int n, q; cin >> n >> q; cin >> s, s = '@' + s; for(int i = 0; i < 26; i++) SegTree::build(1, i, 1, n); while(q--){ int l, r, k; cin >> l >> r >> k; vector<int> cnt; for(int i = 0; i < 26; i++) cnt.emplace_back(SegTree::query(1, i, 1, n, l, r)); if(k){ int curl = l, curr = l; for(int i = 0; i < 26; i++){ if(!cnt[i]) continue; curr = curl + cnt[i] - 1; SegTree::update(1, i, 1, n, l, r, 0); SegTree::update(1, i, 1, n, curl, curr, 1); curl = curr + 1; } assert(curr == r); } else { int curl = l, curr = l; for(int i = 25; i >= 0; i--){ if(!cnt[i]) continue; curr = curl + cnt[i] - 1; SegTree::update(1, i, 1, n, l, r, 0); SegTree::update(1, i, 1, n, curl, curr, 1); curl = curr + 1; } assert(curr == r); } } for(int i = 0; i < 26; i++) SegTree::getans(1, i, 1, n); for(int i = 1; i <= n; i++) cout << ans[i]; cout << endl; } signed main(){ ios_base::sync_with_stdio(false), cin.tie(0); cout << fixed << setprecision(12); int t = 1; //cin >> t; while(t--) solve(); return 0; }

最后

以上就是优秀母鸡最近收集整理的关于12.CF558E A Simple Task 线段树维护字符串区间排序12.CF558E A Simple Task 线段树维护字符串区间排序的全部内容,更多相关12.CF558E内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部