CF #312 E. A Simple Task 线段树
题目链接:http://codeforces.com/problemset/problem/558/E
给一个字符串,每次对一个区间内的子串进行升序或者降序的排列,问最后字符串什么样子。
对于字符串排序,计数排序是比一般的排序要快的,但是仍然不能解决本问题。
建立26个线段树,用于统计某个字符在某个区间的情况。
那么如果对【L,R】排序,则先统计所有字符在其中的情况,并且清空该区间,根据每个字符的数量,从a到z去填充应该在的小区间。
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <numeric>
#include <cassert> using namespace std; const int N=1e5+; char s[N]; struct SegmentTree {
#define M N*4
int val[M];
int flag[M];
void up(int rt) {
val[rt]=val[rt<<]+val[rt<<|];
}
void build(int l,int r,int rt) {
if (l==r) {
val[rt]=;
flag[rt]=-;
return;
}
int m=(l+r)>>;
build(l,m,rt<<);
build(m+,r,rt<<|);
up(rt);
}
void down(int rt,int m=) {
if (flag[rt]!=-) {
flag[rt<<]=flag[rt];
flag[rt<<|]=flag[rt];
if (flag[rt]==){
val[rt<<]=m-(m>>);
val[rt<<|]=(m>>);
}
else {
val[rt<<]=;
val[rt<<|]=;
}
flag[rt]=-;
}
}
void update(int p,int c,int l,int r,int rt) {
if (l==r) {
val[rt]=c;
return;
}
down(rt,r-l+);
int m=(l+r)>>;
if (p<=m)
update(p,c,l,m,rt<<);
else
update(p,c,m+,r,rt<<|);
up(rt);
}
void update(int L,int R,bool c,int l,int r,int rt) {
if (L<=l&&r<=R) {
val[rt]=c?(r-l+):;
flag[rt]=c;
return;
}
down(rt,r-l+);
int m=(l+r)>>;
if (L<=m) update(L,R,c,l,m,rt<<);
if (R>m) update(L,R,c,m+,r,rt<<|);
up(rt);
}
int query(int p,int l,int r,int rt) {
if (l==r) {
return val[rt];
}
down(rt,r-l+);
int m=(l+r>>);
if (p<=m) return query(p,l,m,rt<<);
else return query(p,m+,r,rt<<|);
}
int query(int L,int R,int l,int r,int rt) {
if (L<=l&&r<=R) {
return val[rt];
}
down(rt,r-l+);
int m=(l+r)>>;
int ret=;
if (L<=m) ret+=query(L,R,l,m,rt<<);
if (R>m) ret+=query(L,R,m+,r,rt<<|);
return ret;
}
#undef M
}seg[]; int main() {
int n,q;
scanf("%d %d",&n,&q);
scanf("%s",s+);
for (int i=;i<;i++)
seg[i].build(,n,);
for (int i=;i<=n;i++) {
int p=s[i]-'a';
seg[p].update(i,,,n,);
//cout<<p<<" xxx"<<endl;
}
while (q--) {
int l,r,t;
scanf("%d %d %d",&l,&r,&t);
int cnt[];
for (int i=;i<;i++) {
cnt[i]=seg[i].query(l,r,,n,);
if (cnt[i]>){
seg[i].update(l,r,,,n,);
}
}
if (t==) {
for (int i=;i<;l+=cnt[i++]){
if (cnt[i]==) continue;
seg[i].update(l,l+cnt[i]-,,,n,);
}
}
else {
for (int i=;i>=;l+=cnt[i--]){
if (cnt[i]==) continue;
seg[i].update(l,l+cnt[i]-,,,n,);
}
}
}
for (int i=;i<=n;i++) {
for (int j=;j<;j++){
if (seg[j].query(i,,n,)) {
s[i]='a'+j;
break;
}
}
}
s[n+]=;
printf("%s\n",s+);
return ;
}
CF #312 E. A Simple Task 线段树的更多相关文章
- 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 ...
- Codeforces Round #312 (Div. 2) E. A Simple Task 线段树 延时标记
E. A Simple Task time limit per test5 seconds memory limit per test512 megabytes inputstandard input ...
- CodeForces 588E A Simple Task(线段树)
This task is very simple. Given a string S of length n and q queries each query is on the format i j ...
- Codeforces 588E. A Simple Task (线段树+计数排序思想)
题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...
- CF#312 558e A Simple Task
~~~题面~~~ 题解: 观察到字母只有26个,因此考虑对这26个字母分别维护,每个线段树维护一个字母,如果一个线段树的某个叶节点有值,表示当前叶节点所在位置的字母是现在这个线段树代表的字母. 那么对 ...
- CF558E A simple task 线段树
这道题好猥琐啊啊啊啊啊啊 写了一个上午啊啊啊啊 没有在update里写pushup啊啊啊啊 题目大意: 给你一个字符串s,有q个操作 l r 1 :把sl..rsl..r按升序排序 l r 0 :把s ...
- codeforces 558E A Simple Task 线段树
题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...
- [Codeforces558E]A Simple Task 线段树
链接 题意:给定一个长度不超过 \(10^5\) 的字符串(小写英文字母),和不超过5000个操作. 每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序. 最后输出最终 ...
随机推荐
- Java垃圾回收学习笔记
通常来说,要写Java代码,你基本上都没必要听说垃圾回收这个概念的.这不,对于已经写了5年多Java代码的我来说,我还没有哪次经历说是需要使用垃圾回收方面的知识来解决问题的.但是,我依然督促自己花了几 ...
- wemall app商城源码中基于JAVA的Android异步加载图片管理器代码
wemall doraemon是Android客户端程序,服务端采用wemall微信商城,不对原商城做任何修改,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可随意定制修改.本文分享其中 ...
- CoreAnimation 开篇
CoreAnimation 开篇 CoreAnimation系列博客是我对学习CoreAnimation的知识整理,博客排列顺序以及知识讲解存在欠缺望见谅. 博客的编写是在工作之余,尽量保证CoreA ...
- 机器学习基石 1 The Learning Problem
机器学习基石 1 The Learning Problem Introduction 什么是机器学习 机器学习是计算机通过数据和计算获得一定技巧的过程. 为什么需要机器学习 1 人无法获取数据或者数据 ...
- Android开发使用的常见第三方框架
1.SlidingMenu 官网:https://github.com/jfeinstein10/SlidingMenu 网友使用:http://blog.csdn.net/yangyu2012122 ...
- 2.WP8.1开发_在顶部显示标题和进度
有时候加载页面的时候,需要在信号那一栏显示进度,或者把信号栏改成标题 1.确保显示状态栏.默认显示.如果不显示,可以在应用程序启动后手动用代码显示,代码如下: //取得状态栏 StatusBar ba ...
- Struts2之标签使用
上一篇我们一起探讨了Struts2中的OGNL表达式的知识,本篇我们一起来学习一下关于Struts2标签的使用,包括:基础标签:property.set.bean.include:判断标签:if el ...
- iOS开发之NSOperation & NSOperationQueue
1.简介 (1) NSOperationQueue(操作队列)是由GCD提供的队列模型的Cocoa抽象,是一套Objective-C的API,为了使并发(多线程)编程变得更加简单,但效率比GCD略低. ...
- 使用关系型数据库作为Redis落地的思路
Redis的持久化方式主要有2种:RDB和AOF,但各有不足,同时Redis没有SQL支持,Redis本身提供的命令不足以实现大多数SQL查询需求,对后期运营的分析需求支撑不足.此外,对于游戏来说,活 ...
- android 开机自启动实现
App的开机自启动可以通过注册广播接收器接收开机广播来实现,具体步骤如下: 1.创建 BroadcastReceiver 的派生类,并重写 onReceive() 函数: /** * Created ...