Codeforces 558E A Simple Task(计数排序+线段树优化)
http://codeforces.com/problemset/problem/558/E

Examples
input 1
abacdabcda
output 1
cbcaaaabdd
input 2
agjucbvdfk
output 2
abcdfgjkuv
题意:
给出一个字母的序列(只包含小写字母),每次对它的一个区间进行排序(递增或递减),问最后的字母序列。
自闭题,身为蒟蒻的我读完题后单纯的觉得这题如名字一一样一个简单的任务(完全没有意识到问题的严重性),直接sort走起,结果。。。该题数据规模很大 排序是关键,要想到计数排序
看了题解,真好,26颗线段树,人否?
题解:
采用计数排序的复杂度是O(n∗q),无法通过,但有所启示。
可以看出计数就是区间求和,排序就是区间更新,可以用线段树维护。
做法是建立26棵线段树,第i棵树维护第i个字母的位置信息。
计数时,在26棵线段树内对[L,R]分别做一次查询,统计区间[L,R]中每个字母的个数,排序时根据递增还是递减,在相应的区间内按照字母的顺序(升序或降序)依次重新填进区间内。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <queue>
#include <set>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const double PI=acos(-);
const int maxn=1e5+;
using namespace std; int n,q;
char str[maxn]; struct Tree
{
int sum;
int l;
int r;
int lazy;
}; struct SegmentTree
{
Tree tree[maxn<<];
void PushUp(int rt)
{
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
}
void PushDown(int rt)
{
int lazy=tree[rt].lazy;
if(lazy!=-)
{
tree[rt<<].lazy=tree[rt<<|].lazy=lazy;
tree[rt<<].sum=(tree[rt<<].r-tree[rt<<].l+)*lazy;
tree[rt<<|].sum=(tree[rt<<|].r-tree[rt<<|].l+)*lazy;
tree[rt].lazy=-;
}
}
void Build(int rt,int l,int r,int id)//建树
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].lazy=-;
if(l==r)
{
if(str[l]-'a'==id) tree[rt].sum=;
else tree[rt].sum=;
return ;
}
int m=(l+r)>>;
Build(rt<<,l,m,id);
Build(rt<<|,m+,r,id);
PushUp(rt);
}
void Update(int rt,int L,int R,int v)//区间更新
{
int l=tree[rt].l;
int r=tree[rt].r;
if(L<=l&&R>=r)
{
tree[rt].sum=(r-l+)*v;
tree[rt].lazy=v;
return ;
}
PushDown(rt);
int m=(l+r)>>;
if(L<=m&&R>=l)
Update(rt<<,L,R,v);
if(R>m&&L<=r)
Update(rt<<|,L,R,v);
PushUp(rt);
}
int Query(int rt,int L,int R)//区间查询
{
int l=tree[rt].l;
int r=tree[rt].r;
if(L<=l&&R>=r)
return tree[rt].sum;
PushDown(rt);
int m=(l+r)>>;
int sum=;
if(L<=m&&R>=l)
sum+=Query(rt<<,L,R);
if(R>m&&L<=r)
sum+=Query(rt<<|,L,R);
return sum;
}
}SegTree[]; int main()
{
scanf("%d %d",&n,&q);
scanf("%s",str+);
for(int i=;i<;i++)//建立26个线段树
{
SegTree[i].Build(,,n,i);
}
while(q--)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
int num[];//记录区间内每个字母的个数
for(int i=;i<;i++)
{
num[i]=SegTree[i].Query(,a,b);
SegTree[i].Update(,a,b,);//将该区间内的字母消去
}
int l=a;//l指向要填入区间的头
if(c)//升序填入
{
for(int i=;i<;i++)
{
SegTree[i].Update(,l,l+num[i]-,);
l+=num[i];
}
}
else//降序填入
{
for(int i=;i>=;i--)
{
SegTree[i].Update(,l,l+num[i]-,);
l+=num[i];
}
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<;j++)
{
if(SegTree[j].Query(,i,i))
{
printf("%c",j+'a');
}
}
}
printf("\n");
return ;
}
Codeforces 558E A Simple Task(计数排序+线段树优化)的更多相关文章
- Codeforces 558E A Simple Task (计数排序&&线段树优化)
题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...
- CodeForces 558E(计数排序+线段树优化)
题意:一个长度为n的字符串(只包含26个小字母)有q次操作 对于每次操作 给一个区间 和k k为1把该区间的字符不降序排序 k为0把该区间的字符不升序排序 求q次操作后所得字符串 思路: 该题数据规模 ...
- 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task
E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...
- Nowcoder Hash Function ( 拓扑排序 && 线段树优化建图 )
题目链接 题意 : 给出一个哈希表.其避免冲突的方法是线性探测再散列.现在问你给出的哈希表是否合法.如果合法则输出所有元素插入的顺序.如果有多解则输出字典序最小的那一个.如果不合法则输出 -1 分析 ...
- Codeforces 1603D - Artistic Partition(莫反+线段树优化 dp)
Codeforces 题面传送门 & 洛谷题面传送门 学 whk 时比较无聊开了道题做做发现是道神题( 介绍一种不太一样的做法,不观察出决策单调性也可以做. 首先一个很 trivial 的 o ...
- Codeforces.1045A.Last chance(最大流ISAP 线段树优化建图)
题目链接 \(Description\) 你需要用给定的\(n\)个武器摧毁\(m\)架飞船中的某一些.每架飞船需要被摧毁恰好一次. 武器共三种:1.可以在给定的集合中摧毁一架飞船:2.可以摧毁区间\ ...
- Codeforces 558E A Simple Task(权值线段树)
题目链接 A Simple Task 题意 给出一个小写字母序列和若干操作.每个操作为对给定区间进行升序排序或降序排序. 考虑权值线段树. 建立26棵权值线段树.每次操作的时候先把26棵线段树上的 ...
- codeforces 558E A Simple Task 线段树
题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...
- Codeforces 558E A Simple Task
题意:给定一个字符串,以及m次操作,每次操作对字符串的一个子区间进行升序或降序排序,求m次操作后的串 考虑桶排,发现线段树可以模拟桶排的过程,所以对26个字母分别建立线段树即可 #include< ...
随机推荐
- IDEA控制台输出中文乱码日志文件正常
控制台中文输出乱码但输出的日志文件正常 idea.exe.vmoptions与idea64.exe.vmoptions已经配置 -Dfile.encoding=UTF-8 logback.xml中也配 ...
- (递归)P1025 数的划分
题解: #include<iostream>using namespace std;int ret=0,m_n;void p(int n,double k,int j){ if(k==1) ...
- HDU 5312:Sequence
Sequence Accepts: 25 Submissions: 1442 Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 2621 ...
- 113.Pageinator和Page类常用的属性和方法
Paginator和Page类: Paginator和Page类都是用来分页的,他们在Django中的路径为django.core.paginator.Pageinator和django.core.p ...
- 逃生(地图上的dp)
蒜头君在玩一款逃生的游戏.在一个n×m 的矩形地图上,蒜头位于其中一个点.地图上每个格子有加血的药剂,和掉血的火焰,药剂的药效不同,火焰的大小也不同,每个格子上有一个数字,如果格子上的数字是正数说明是 ...
- kafka分区选主机制
Kafka Partition Leader选主机制 https://blog.csdn.net/qq_27384769/article/details/80115392 kafka leader选举 ...
- 【Pytyon模块】logging模块-日志处理
一.日志相关概念 1.日志的作用 通过log的分析,可以方便用户了解系统或软件.应用的运行情况:如果你的应用log足够丰富,也可以分析以往用户的操作行为.类型喜好.地域分布或其他更多信息:如果一个应用 ...
- js对象属性名和属性值生成新数组时都作为属性值
const obj = { id:1, name:'zhangsan', age:18 } const arr = []; Object.getOwnPropertyNames(obj).forEac ...
- 寒假day11
毕设数据抽取部分还有一点问题,正在修改中
- linux.linuxidc.com - /2011年资料/Android入门教程/
本文转自 http://itindex.net/detail/15843-linux.linuxidc.com-%E8%B5%84%E6%96%99-android Shared by Yuan 用户 ...
