CF240F (26颗线段树计数)
题目链接: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颗线段树计数)的更多相关文章
- 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 ...
- Codeforces 588E. A Simple Task (线段树+计数排序思想)
题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...
- ACM-ICPC 2018 徐州赛区网络预赛 G Trace(逆向,两颗线段树写法)
https://nanti.jisuanke.com/t/31459 思路 凡是后面的轨迹对前面的轨迹有影响的,可以尝试从后往前扫 区间修改需要push_down,单点更新所以不需要push_up(用 ...
- HDU 4267 A Simple Problem with Integers(2012年长春网络赛A 多颗线段树+单点查询)
以前似乎做过类似的不过当时完全不会.现在看到就有点思路了,开始还有洋洋得意得觉得自己有不小的进步了,结果思路错了...改了很久后测试数据过了还果断爆空间... 给你一串数字A,然后是两种操作: &qu ...
- HDU 3954 Level up(多颗线段树+lazy操作)
又是一开始觉得的水题,结果GG了好久的东西... 题意是给你n个英雄,每个英雄开始为1级经验为0,最多可以升到k级并且经验一直叠加,每一级都有一个经验值上限,达到就升级.接着给你两种操作:W li r ...
- CF 85D Sum of Medians (五颗线段树)
http://codeforces.com/problemset/problem/85/D 题意: 给你N(0<N<1e5)次操作,每次操作有3种方式, 1.向集合里加一个数a(0< ...
- Codeforces - 240F 是男人就上26棵线段树
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+11; typedef long long ll; ch ...
- Codeforces 558E A Simple Task(计数排序+线段树优化)
http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...
- CF558E-A Simple Task-线段树+计数排序
计数排序的原理,只要知道了有几个数比i小,就可以知道i的位置 这道题只有26个字母,搞26颗线段树,然后区间更新 #include <cstdio> #include <cstrin ...
随机推荐
- Java SE 17 新增特性
Java SE 17 新增特性 作者:Grey 原文地址:Java SE 17 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- RabbitMQ 入门系列:5、基础编码:交换机的进阶介绍及编码方式。
系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...
- Linux应急响应学习
Linux应急响应-系统日志排查-溯源 溯源 找到攻击者.系统日志分析攻击者的ip 攻击者可能留下了一些代码 样本 网上的信息很大程度上是不可信的. 方法: 蜜罐 高交互的蜜罐 溯源: ip 日志 ...
- Clickhouse基准测试实践
1.概述 本篇博客将对MySQL.InfluxDB.Clickhouse在写入时间.聚合查询时间.磁盘使用等方面的性能指标来进行比较. 2.内容 比较的数据集,是使用的Clickhouse官网提供的6 ...
- 【JDBC】学习路径8-连接池
为什么是连接池? 第一.受我们硬件资源的限制,我们的一些资源使用时有限制的比如我们的数据库 连接数和线程数.为了摆脱这些限制,我们就使用了池化技术来将这些资源限制在一定范围内. 第二.我们创建和销毁这 ...
- 「题解报告」P2154 虔诚的墓主人
P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...
- 状态 :睡眠中,进程ID:13431,yum提示Another app is currently holding the yum lock; waiting for it to exit...
问题描述: 今天想在虚拟机上重新安装docker然后使用到yum命令报错: 解决办法: [root@localhost ~]# rm -f /var/run/yum.pid 然后重新运行刚才的yum命 ...
- Docker 安装 MySQL、Redis
1 Docker 中安装 Redis 1.1 创建目录 在硬盘上创建 redis 的数据目录: mkdir -p /Users/yygnb/dockerMe/redis/data 为该目录添加权限: ...
- SUSE Linux Enterprise Server 12 使用二进制文件安装docker
Docker-CE in SUSE 虽然使用zypper添加源也能安装,不过我在SLES 12sp5 上安装时发现好多命令还需要自己手动软连接,干脆网上找了找文档,再自己小改下,用二进制部署,也是可以 ...
- Python入门系列(十)一篇学会python文件处理
文件处理 在Python中处理文件的关键函数是open()函数.有四种不同的方法(模式)来打开一个文件 "r" - 读取 - 默认值.打开一个文件进行读取,如果文件不存在则出错. ...