题目链接:Topcoder----洛谷

题目大意:

  给定一个长为n的由a到z组成的字符串,有m次操作,每次操作将[l,r]这些位置的字符进行重排,得到字典序最小的回文字符串,如果无法操作就不进行。

思路:

  用26颗线段树分别统计在每个位置上是否有对应的字母

  每次操作:

    1.有出现次数为奇数的字母:

      大于1,不可能回文,无法操作。

      等于1,放到中间

    2.全是偶数次数:

      分别放两端

  1 # include<bits/stdc++.h>
2 using namespace std;
3 #define endl "\n"
4 # define int long long
5 # define ls u<<1
6 # define rs u<<1|1
7 const int N = 1e5 + 10;
8 char a[N], p;
9 int n, m;
10 struct segtree {
11 int sum[4 * N], lazy[4 * N];
12 void pushup(int u) {
13 sum[u] = (sum[ls] + sum[rs]);
14 }
15
16 void build(int tr, int u, int l, int r) {
17 lazy[u] = -1;
18 if (l == r) {
19 sum[u] = ((a[l] - 'a' ) == tr);
20 return;
21 }
22 int mid = l + r >> 1;
23 build(tr, ls, l, mid);
24 build(tr, rs, mid + 1, r);
25 pushup(u);
26 }
27
28 void pushdown(int u, int l, int r) {
29 int mid = l + r >> 1;
30 if (lazy[u] != -1) {
31 sum[ls] = (mid - l + 1) * lazy[u];
32 sum[rs] = (r - mid) * lazy[u];
33
34 lazy[ls] = lazy[u];
35 lazy[rs] = lazy[u];
36 lazy[u] = -1;
37 }
38
39 }
40
41 void modify(int u, int l, int r, int L, int R, int c) {
42 if (l > r || l > R || r < L) return;
43 if (L <= l && r <= R) {
44 sum[u] = (r - l + 1) * c;
45 lazy[u] = c;
46 return;
47 }
48 int mid = l + r >> 1;
49 pushdown(u, l, r);
50 if (L <= mid) modify(ls, l, mid, L, R, c);
51 if (mid + 1 <= R) modify(rs, mid + 1, r, L, R, c);
52 pushup(u);
53 }
54
55 int query(int u, int l, int r, int L, int R) {
56 if (l > r || l > R || r < L) return 0;
57 if (l >= L && r <= R) {
58 return sum[u];
59 }
60 pushdown(u, l, r);
61 int mid = l + r >> 1;
62 int ans = 0;
63 if (L <= mid) ans += query(ls, l, mid, L, R);
64 if (R > mid) ans += query(rs, mid + 1, r, L, R);
65 return ans;
66 }
67 } tr[26];
68
69 signed main() {
70 ios::sync_with_stdio(false);
71 cin.tie(0);
72 cout.tie(0);
73 freopen("input.txt", "r", stdin);
74 freopen("output.txt", "w", stdout);
75 cin >> n >> m;
76 string s;
77 cin >> s;
78 for (int i = 1; i <= n; ++i) a[i] = s[i - 1];
79 for (int i = 0; i < 26; ++i) tr[i].build(i, 1, 1, n);
80 for (int t = 1; t <= m; ++t) {
81 int l, r;
82 cin >> l >> r;
83 int odd = 0;
84 int tmp[26] = {0}, key;
85 for (int i = 0; i < 26; ++i) tmp[i] = tr[i].query(1, 1, n, l, r);//记录在区间[l,r]中每个字母出现的次数
86 for (int i = 0; i < 26; ++i) if (tmp[i] & 1) odd++, key = i;
87 if (odd > 1) continue;
88 for (int i = 0; i < 26; ++i) tr[i].modify(1, 1, n, l, r, 0);
89 if (odd) {
90 --tmp[key];
91 tr[key].modify(1, 1, n, (l + r) / 2, (l + r) / 2, 1);//奇数置中
92 }
93 int nl = l, nr = r;
94 for (int i = 0; i < 26; ++i) {//偶数分两边放
95 if (tmp[i]) {
96 tr[i].modify(1, 1, n, nl, nl + tmp[i] / 2 - 1, 1);
97 nl += tmp[i] / 2;
98 tr[i].modify(1, 1, n, nr - tmp[i] / 2 + 1, nr, 1);
99 nr -= tmp[i] / 2;
100 }
101 }
102 }
103 for (int i = 1; i <= n; ++i) {
104 for (int j = 0; j < 26; ++j) {
105 if (tr[j].query(1, 1, n, i, i)) {
106 cout << (char)(j + 'a');
107 }
108 }
109 }
110 return 0;
111 }

 

CF240F (26颗线段树计数)的更多相关文章

  1. Codeforces Round #312 (Div. 2) E. A Simple Task 线段树+计数排序

    题目链接: http://codeforces.com/problemset/problem/558/E E. A Simple Task time limit per test5 secondsme ...

  2. Codeforces 588E. A Simple Task (线段树+计数排序思想)

    题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...

  3. ACM-ICPC 2018 徐州赛区网络预赛 G Trace(逆向,两颗线段树写法)

    https://nanti.jisuanke.com/t/31459 思路 凡是后面的轨迹对前面的轨迹有影响的,可以尝试从后往前扫 区间修改需要push_down,单点更新所以不需要push_up(用 ...

  4. HDU 4267 A Simple Problem with Integers(2012年长春网络赛A 多颗线段树+单点查询)

    以前似乎做过类似的不过当时完全不会.现在看到就有点思路了,开始还有洋洋得意得觉得自己有不小的进步了,结果思路错了...改了很久后测试数据过了还果断爆空间... 给你一串数字A,然后是两种操作: &qu ...

  5. HDU 3954 Level up(多颗线段树+lazy操作)

    又是一开始觉得的水题,结果GG了好久的东西... 题意是给你n个英雄,每个英雄开始为1级经验为0,最多可以升到k级并且经验一直叠加,每一级都有一个经验值上限,达到就升级.接着给你两种操作:W li r ...

  6. CF 85D Sum of Medians (五颗线段树)

    http://codeforces.com/problemset/problem/85/D 题意: 给你N(0<N<1e5)次操作,每次操作有3种方式, 1.向集合里加一个数a(0< ...

  7. Codeforces - 240F 是男人就上26棵线段树

    #include<bits/stdc++.h> using namespace std; const int maxn = 1e5+11; typedef long long ll; ch ...

  8. Codeforces 558E A Simple Task(计数排序+线段树优化)

    http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...

  9. CF558E-A Simple Task-线段树+计数排序

    计数排序的原理,只要知道了有几个数比i小,就可以知道i的位置 这道题只有26个字母,搞26颗线段树,然后区间更新 #include <cstdio> #include <cstrin ...

随机推荐

  1. 054_末晨曦Vue技术_处理边界情况之组件之间的循环引用

    组件之间的循环引用 点击打开视频讲解更详细 假设你需要构建一个文件目录树,像访达或资源管理器那样的.你可能有一个 <tree-folder> 组件,模板是这样的: <p> &l ...

  2. 垃圾收集器 参阅<<深入理解JAVA虚拟机>>

    一.新生代 1.Serial收集器 新生代单线程复制算法GC(暂停工作线程)---------- 支持组合老年代Serial odl和CMS 2.ParNew Serial多线程版本 支持组合cms| ...

  3. Windows权限维持总结

    windows权限维持 注册服务 sc create 服务名 binpath= "cmd.exe /k 木马路径" start="auto" obj=" ...

  4. Session认证机制与JWT认证机制

    一.什么是身份认证? 身份认证(Authentication)又称"身份验证"."鉴权",是指通过一定的手段,完成对用户身份的确认.日常生活中的身份认证随处可见 ...

  5. K8S name_namespace

    Name 由于K8S内部,使用"资源"来定义每一种逻辑概念(功能),故没种"资源",都应该有自己的"名称" "资源"有 ...

  6. P8539 「Wdoi-2」来自地上的支援 题解

    思路 根据题意,如果每次询问选中的为第 \(x\) 个数,那么前 \(x-1\) 次操作一定不会选中第 \(x\) 个数.(感觉在说废话.) 同样,因为第 \(x\) 个数必须被选中 \(k\) 次, ...

  7. Java SE final关键字

    final关键字 final可以修饰类.属性.方法和局部变量 如下情况,可以使用final 当不希望类被继承时,可以用final修饰 当不希望父类的某个方法被子类覆盖/重写(override)时,可以 ...

  8. jmeter性能测试之正则提取响应头或者响应体

    准备工作做好,先发送请求 然后察看结果树中的响应消息 比如我们要提取这个cookie,先调试一下,看能不能提取到 看蓝色的线条,我们提取到了,然后我们把这句话写入到后置处理器中的正则表达式提取里 再次 ...

  9. 尝试阅读理解一份linux shell脚本

    以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/p/16721350.html 从头一二去阅读语法和命令说明 ...

  10. MinIO Python Client SDK 快速入门指南

    官方文档地址:http://docs.minio.org.cn/docs/master/python-client-quickstart-guide MinIO Python Client SDK提供 ...