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 ...
随机推荐
- mac使用brew或者tomcat启动jenkins后配置文件路径
在mac下使用brew命令或tomcat安装jenkins,启动后要输入密码,密码不知道,又找不到config.xml,找了半天原来 config.xml在/Users/qiaojiafei/.jen ...
- linux部署MantisBT(二)部署php
二.部署php 1.下载php安装包 http://php.net/downloads.php 2.安装php yum install libxml2 yum install libxml2-deve ...
- 【SpringCloud】第五篇: 路由网关(zuul)
前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...
- Linux命令应用大词典-第6章 文件处理
6.1 sort:对文件中的数据进行排序 6.2 uniq:将重复行从输出文件中删除 6.3 cut:从文件每行中输出选定的字节.字符或字段 6.4 comm:逐行比较两个已经排序的文件 6.5 di ...
- MongoDB->NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"
关系型数据库遵循ACID规则 事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性: 1.A (Atomicity) 原子性 原子性很容易理解,也就是说事务里的所有操作要么 ...
- Python3 Tkinter-Listbox
1.创建 from tkinter import * root=Tk() lb=Listbox(root) for item in ['python','tkinter','widget']: lb. ...
- 基础数据类型-set
Set是无序不重复元素的序列,基本功能是删除重复元素和测试成员关系, 创建一个集合可以用set()或者({}),但是创建一个空集合只能用set(): s1 = set() print("s1 ...
- SGU 438 The Glorious Karlutka River =)(最大流)
Description A group of Mtourists are walking along the Karlutka river. They want to cross the river, ...
- Lecture Sleep(尺取+前缀和)
Description 你的朋友Mishka和你参加一个微积分讲座.讲座持续n分钟.讲师在第i分钟讲述ai个定理. 米什卡真的对微积分很感兴趣,尽管在演讲的所有时间都很难保持清醒.给你一个米什卡行 ...
- Python3.5在Windows7环境下Scrapy库的安装
Python3.5在Windows7环境下Scrapy库的安装 忙活了一下午,总算是把Scrapy库给装完了,记下来给需要帮助的人 首先安装的环境:Windows7 64位 Python的版本是:3. ...