CF#312 558e A Simple Task
题解:
观察到字母只有26个,因此考虑对这26个字母分别维护,每个线段树维护一个字母,如果一个线段树的某个叶节点有值,表示当前叶节点所在位置的字母是现在这个线段树代表的字母。
那么对于每一个操作,我们已经知道最后排好序之后肯定是按aaaabbbbccccddd……这样的序列排下去的(有些字母可能没有),每个字母都集中在自己的区间内。
那么我们只需要知道每个字母之前的字母有多少个,就可以知道这个字母所在区间,因此按顺序修改。
(以下操作均视为在每个字母对应的线段树上操作)先查询a的个数,并把当前修改的区间内赋0,然后把前1~tot_a全都赋1,表示这段区间是属于a的(全都放上1)。
记在统计当前字母之前找到的字母个数之和为tot,则每次都是把当前线段树管理的字母全都移动到tot + 1~tot + 字母个数,相当于跟修改a类似的区间操作。只不过属于这个字母的区间的开始端点是tot + 1(其实a的情况也可以视作是tot + 1,因为这个时候tot = 0)
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define LL long long
#define AC 101000
#define ac 401000 int n, m, id, tot, add, t;
int l[ac], r[ac];
char s[AC], ans[AC]; int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c -'', c = getchar();
return x;
} inline void upmin(int &a, int b)
{
if(b < a) a = b;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} struct segament_tree{
int tree[ac], lazy[ac], id; inline void init()
{
memset(lazy, -, sizeof(lazy));
} inline void update(int x)
{
tree[x] = tree[x * ] + tree[x * + ];
} inline void pushdown(int x)
{
if(lazy[x] != -)
{
int ll = x * , rr = ll + ;
lazy[ll] = lazy[rr] = lazy[x];
if(!lazy[x]) tree[ll] = tree[rr] = ;
else
{
int mid = (l[x] + r[x]) >> ;
tree[ll] = mid - l[ll] + ;
tree[rr] = r[rr] - mid;
}
lazy[x] = -;
}
} void build(int x, int ll, int rr)
{
if(!id) l[x] = ll, r[x] = rr;
if(ll == rr)
{
if(s[ll] == id + 'a') tree[x] = ;
return ;
}
int mid = (ll + rr) >> ;
build(x * , ll, mid);
build(x * + , mid + , rr);
update(x);
} void find(int x, int ll, int rr)
{
if(!tree[x]) return ;
if(l[x] == ll && r[x] == rr){add += tree[x]; return ;}
pushdown(x);
int mid = (l[x] + r[x]) >> ;
if(rr <= mid) find(x * , ll, rr);
else if(ll > mid) find(x * + , ll, rr);
else
{
find(x * , ll, mid);
find(x * + , mid + , rr);
}
update(x);
} void change(int x, int ll, int rr)
{
if(l[x] == ll && r[x] == rr)
{
lazy[x] = t;
if(t) tree[x] = rr - ll + ;
else tree[x] = ;
return ;
}
pushdown(x);
int mid = (l[x] + r[x]) >> ;
if(rr <= mid) change(x * , ll, rr);
else if(ll > mid) change(x * + , ll, rr);
else
{
change(x * , ll, mid);
change(x * + , mid + , rr);
}
update(x);
} void get(int x)
{
if(!tree[x]) return ;
if(tree[x] == r[x] - l[x] + )
{
for(R i = l[x]; i <= r[x]; i ++) ans[i] = id + 'a';
return ;
}
pushdown(x);
if(tree[x * ]) get(x * );
if(tree[x * + ]) get(x * + );
} }T[]; void pre()
{
n = read(), m = read();
scanf("%s", s + );
for(R i = ; i < ; i ++)
T[i].id = i, T[i].init(), T[i].build(, , n);
} void check()
{
for(R i = ; i < ; i ++) T[i].get();
for(R i = ; i <= n; i ++) printf("%c", ans[i]);
printf("\n");
} void work()
{
int ll, rr, opt;
for(R i = ; i <= m; i ++)
{
// printf("%d\n", i);
ll = read(), rr = read(), opt = read(), tot = ll - ;
if(opt)
{
for(R j = ; j < ; j ++)
{
add = t = ;
T[j].find(, ll, rr);
if(!add) continue;
T[j].change(, ll, rr);
t = ;
T[j].change(, tot + , tot + add);
tot += add;
}
//check();
}
else
{
for(R j = ; j >= ; j --)
{
add = t = ;
T[j].find(, ll, rr);
if(!add) continue;
T[j].change(, ll, rr);
t = ;
T[j].change(, tot + , tot + add);
tot += add;
}
// check();
}
}
for(R i = ; i < ; i ++) T[i].get();
for(R i = ; i <= n; i ++) printf("%c", ans[i]);
printf("\n");
} int main()
{
//freopen("string6.in", "r", stdin);
pre();
work();
//fclose(stdin);
return ;
}
CF#312 558e A Simple Task的更多相关文章
- CF #312 E. A Simple Task 线段树
题目链接:http://codeforces.com/problemset/problem/558/E 给一个字符串,每次对一个区间内的子串进行升序或者降序的排列,问最后字符串什么样子. 对于字符串排 ...
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...
- Codeforces 558E A Simple Task (计数排序&&线段树优化)
题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...
- Codeforces 558E A Simple Task(权值线段树)
题目链接 A Simple Task 题意 给出一个小写字母序列和若干操作.每个操作为对给定区间进行升序排序或降序排序. 考虑权值线段树. 建立26棵权值线段树.每次操作的时候先把26棵线段树上的 ...
- Codeforces 558E A Simple Task
题意:给定一个字符串,以及m次操作,每次操作对字符串的一个子区间进行升序或降序排序,求m次操作后的串 考虑桶排,发现线段树可以模拟桶排的过程,所以对26个字母分别建立线段树即可 #include< ...
- codeforces 558E A Simple Task 线段树
题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...
- Codeforces 558E A Simple Task(计数排序+线段树优化)
http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...
- Codeforces Round #312 (Div. 2) E. A Simple Task 线段树
E. A Simple Task 题目连接: http://www.codeforces.com/contest/558/problem/E Description This task is very ...
- 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 ...
随机推荐
- 180602-nginx多域名配置
文章链接:https://liuyueyi.github.io/hexblog/2018/06/02/180602-nginx多域名配置/ nginx多域名配置 原来的域名过期了,重新买了一个hhui ...
- Selenium(Python)生成Html测试报告
由于Python3已经不支持HTMLTestRunner了, 无论是PyCharm还是pip都无法安装成功, 所以只能去 http://tungwaiyip.info/software/HTMLTes ...
- 给eclipse安装color-theme插件
给eclipse安装color-theme插件 2016年03月22日 19:16:01 ming_love 阅读数:5193 标签: Eclipse Color Theme 更多 个人分类: jav ...
- commons-lang源码解析之StringUtils
apache的commons工具包是平时使用最多的工具包之一,对其实现方式需要具体了解.commons-lang version 3.1 empty和blank的区别 StringUtils中判断St ...
- selenium常用操作方法
Webdriver中比较常用的操作元素的方法: clear() 清除输入框的默认内容 send_keys("xxx") 在一个输入框里输入xx内容 ——如果输入中文,则需要在脚本开 ...
- 孵化器使用Office365的场景及收益
- Python3 数据类型-字符串
字符串是 Python 中最常用的数据类型,是一个个字符组成的有序的序列,是字符的集合. 一 字符串定义 创建字符串很简单,可以使用引号('或"或""")来创建 ...
- 【树莓派 Raspberry-Pi 】用Windows远程桌面连接树莓派的方法【转】
树莓派DIY笔记之前有介绍过用VNC连接到树莓派的方法.在Windows下,当然还是自带的远程桌面更便捷.如果不想用VNC,利用远程桌面(mstsc.exe)连接树莓派,如何实现? 只需要在raspb ...
- 小程序的picker的range 是一个 Object Array (对象数组)
小程序的picker的range 是一个 Object Array (对象数组) 数据: array: [{'id':1,'name':'Android'},{'id':2,'name':'IOS'} ...
- 软件工程第二周PSP