Codeforces J. A Simple Task(多棵线段树)
题目描述:
Description
This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.
Output the final string after applying the queries.
Input
The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively.
Next line contains a string S itself. It contains only lowercase English letters.
Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, ).
Output
Output one line, the string S after applying the queries.
Sample Input
10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1
10 1
agjucbvdfk
1 10 1
Sample Output
cbcaaaabdd
abcdfgjkuv
思路:
题目的意思是,给定一个字符串,有q个询问,要把区间[l,r]的字符根据k的值升序(k=1),或降序(k=0)改变。
因为字母集有26个字母,就可以建立27棵线段树分别维护区间上每个字母出现的次数,一般地,第i棵线段树维护字母i-1+'a'的数目。
维护字母在区间上出现的次数有什么用?想想我们要做的事情,就是把区间[l,r]上的排一个序,字母集有限,想到计数排序,用一个27大小(0不存)的cnt数组,cnt[i]记录字母i出现的次数
如果k是1,则下标从1开始,如果对应那一项不为0,说明区间这个位置要被覆盖成i,就直接覆盖掉原来的线段树对应区间[l,r]上记录的字母i出现的次数,注意这里是直接覆盖,而不是累加,所以要修改线段树模板的区间和的upgrade函数的sum[a][r]+=改为sum[a][r]=,(a表示字母a对应的线段树)对应的懒标记也改为=。
一开始由于循环写的有点长(值代码长度),把计数的变量写叉了,有因为上面没有注意是最直接覆盖,一直出现out of bound错误,一开始还莫名其妙,搞了一个上午一直到晚上才知道写错了(╯‵□′)╯︵┻━┻,bug真好写,改是真难。
一开始写得麻烦了,比如把区间修改成字母a,然后我还在后面有把在这个区间上的,原来的对应的字母对应的线段树,一个位置一个位置的修改,然后提交,超时。。。
咋办嘞?原来只要在开始输入l,r那会统计每个字母在这个区间上出现次数后,紧接着立马删掉原来的数据(区间上的数据全置0),这么一改,好家伙,连样例都过不了了-_-||
找了半天,然后联想到这题的直接覆盖的不同寻常之处,也就是不同于区间和,才发现懒标记我标的有问题,没有懒标记我标0,懒标记为0(区间清零要用的)的还是0,那我在pushdown的时候怎么区分这两种情况呢?
咋办?标奇偶!神奇,覆盖的标记是1,清零的标记是2,没有标记的是0,这样就可以区分,那我咋使用呢?lz%2就行,1就是1,2就是0,可以正常使用了。
这题思路清晰,就是要注意细节,果然还是我太菜了。。
知识点:线段树的覆盖(自编题目)
代码:(开了氧气上瘾了)(注释依稀可见我超时的地方)
#include <iostream>
#include <cstring>
#include <memory.h>
#define max_n 100005
using namespace std;
char s[max_n];
int sum[][max_n<<];
int lz[][max_n<<];
int cnt[];
int n;
int q;
int k;
void pushup(int a,int r)
{
sum[a][r] = sum[a][r<<]+sum[a][r<<|];
}
void build(int a,int r,int lc,int rc)
{
if(lc==rc)
{
if(a==s[lc]-'a'+)
sum[a][r] = ;
lz[a][r] = ;
return;
}
int mid = (lc+rc)>>;
build(a,r<<,lc,mid);
build(a,r<<|,mid+,rc);
pushup(a,r);
}
void pushdown(int a,int r,int ln,int rn)
{
if(lz[a][r])
{
//cout << "r" << r << endl;
sum[a][r<<] = ln*(lz[a][r]%);//注意这里的改变
sum[a][r<<|] = rn*(lz[a][r]%);//还有这里
lz[a][r<<] = lz[a][r];
lz[a][r<<|] = lz[a][r];
lz[a][r] = ;
}
}
void upgrade(int a,int r,int L,int R,int lc,int rc,int val)
{
if(L<=lc&&rc<=R)
{
sum[a][r] = (rc-lc+)*(val%);//这里,这里!
lz[a][r] = val;//直接覆盖就是等于哦
return;
}
int mid = (lc+rc)>>;
pushdown(a,r,mid-lc+,rc-mid);
if(L<=mid) upgrade(a,r<<,L,R,lc,mid,val);
if(mid<R) upgrade(a,r<<|,L,R,mid+,rc,val);
pushup(a,r);
}
int query(int a,int r,int L,int R,int lc,int rc)
{
if(L<=lc&&rc<=R)
{
return sum[a][r];
}
int mid = (lc+rc)>>;
pushdown(a,r,mid-lc+,rc-mid);
int res = ;
if(L<=mid) res += query(a,r<<,L,R,lc,mid);
if(mid<R) res += query(a,r<<|,L,R,mid+,rc);
return res;
}
#pragma optimize(2)
int main()
{
cin >> n >> q;
for(int i = ;i<=n;i++)
{
cin >> s[i];
}
for(int i = ;i<=;i++)
{
build(i,,,n);
}
int l,r,k;
for(int i=;i<q;i++)
{
cin >> l >> r >> k;
for(int j = ;j<=;j++)
{
cnt[j] = query(j,,l,r,,n);
upgrade(j,,l,r,,n,);//直接清零
}
if(k==)
{
int lp = l;
for(int p = ; p<=; p++)
{
if(cnt[p])
{
char ch =p+'a'-;
//cout << ch << ":" << cnt[p] << endl;
upgrade(p,,lp,lp+cnt[p]-,,n,);
lp = lp+cnt[p];
/*for(int j = 0; j<cnt[p];j++)
{
upgrade(s[lp]-'a'+1,1,lp,lp,1,n,-1);
s[lp]=p+'a'-1;
lp++;
}*/
}
}
/*for(int i = 1; i<=n; i++)
{
cout << s[i];
}
cout << endl;*/
}
else
{
int lp = l;
for(int p = ; p>=; p--)
{
if(cnt[p])
{
char ch = p+'a'-;
//cout << ch << ":" << cnt[p] << endl;
upgrade(p,,lp,lp+cnt[p]-,,n,);
lp = lp+cnt[p];
/*for(int j = 0; j<cnt[p];j++)
{
upgrade(s[lp]-'a'+1,1,lp,lp,1,n,-1);
s[lp] = p+'a'-1;
lp++;
}*/ }
}
/*for(int i = 1; i<=n; i++)
{
cout << s[i];
}
cout << endl;*/
}
}
for(int i = ;i<=n;i++)
{
for(int j = ;j<;j++)
{
cnt[j] = query(j,,i,i,,n);
if(cnt[j])
{
char ch = j-+'a';
cout << ch;
}
}
}
cout << endl;
return ;
}
Codeforces J. 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 : A Simple Task
E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...
- 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棵 ...
- Codeforces 558E A Simple Task(计数排序+线段树优化)
http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...
- codeforces 558E A Simple Task 线段树
题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...
- CodeForces - 960F Pathwalks —— 主席树(n棵线段树)
题目链接:https://vjudge.net/problem/CodeForces-960F You are given a directed graph with n nodes and m ed ...
- Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)
Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...
- codeforces 811E Vladik and Entertaining Flags(线段树+并查集)
codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...
随机推荐
- [LeetCode] 342. Power of Four 4的次方数
Given an integer (signed 32 bits), write a function to check whether it is a power of 4. Example:Giv ...
- Git安装和使用(Windows)
Git介绍 分布式:Git版本控制系统是一个分布式的系统,是用来保存工程源代码历史状态的命令行工具. 保存点:Git的保存点可以追踪源码中的文件, 并能得到某一个时间点上的整个工程项目的状态:可以在该 ...
- php_mvc实现步骤八
shop34-10-框架类 框架类(框架初始化类) 将原来入口文件中功能,放在该类中完成,入口文件变得简单,轻量! 将入口文件中的各个功能,由框架类的各个方法,完成: 为了简单化,使用纯静态的类.(看 ...
- Json 文件读写以及和IniFile 转换
JSON 文件是越来越受欢迎了,以前程序配置文件用Ini,Ini 简练,简单.方便,但是也有不少缺点,比如,没有 JSON 直观,无法存储复杂点的数据类型. 于是乎,我封装了一个TJsonFile 的 ...
- 函数的练习1——python编程从入门到实践
8-1 消息: 编写一个名为display_message()的函数,它打印一个句子指出你在本章学的是什么.调用这个函数,确认显示的消息正确无误. def display_message(): pri ...
- FIFO形成3x3矩阵
Verilog生成矩阵一般是使用shift_ip核,但其实用两个FIFO也行.最近刚好学到这种方法,把原理总结一下. 要求 现在有10x5的数据和对应数据有效指示信号,数据为0~49,要用FPGA对其 ...
- git及gitflow命令备忘
全文xxx表示你的分支名 一.git 删除本地分支 git branch -d xxx 删除远程分支 git push origin --delete xxx 查看所有分支 本地分支 git bran ...
- python基础_MySQL的bigint类型
bigint支持的数字的大小范围为:19位,存电话号码.有符号范围:-9223372036854775808 到 9223372036854775807 int支持的数字范围为:10位,有符号范围:- ...
- MySql取消密码强度验证功能
一.修改MySql配置文件(my.cnf)一般情况下,MySql的配置文件 my.cnf 会在 /etc/ 目录下,如果没有,可以使用以下命令查找位置: find / -name my.cnf 编辑 ...
- ThreadPoolExecutor使用错误导致死锁
背景 10月2号凌晨12:08收到报警,所有请求失败,处于完全不可用状态 应用服务器共四台resin,resin之前由四台nginx做负载均衡 服务器现象及故障恢复步骤 登入服务器,观察resin进程 ...