题目描述:

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(多棵线段树)的更多相关文章

  1. Codeforces 558E A Simple Task (计数排序&&线段树优化)

    题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...

  2. 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task

    E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...

  3. 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 ...

  4. Codeforces 588E. A Simple Task (线段树+计数排序思想)

    题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...

  5. Codeforces 558E A Simple Task(计数排序+线段树优化)

    http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...

  6. codeforces 558E A Simple Task 线段树

    题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...

  7. CodeForces - 960F Pathwalks —— 主席树(n棵线段树)

    题目链接:https://vjudge.net/problem/CodeForces-960F You are given a directed graph with n nodes and m ed ...

  8. Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)

    Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...

  9. codeforces 811E Vladik and Entertaining Flags(线段树+并查集)

    codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...

随机推荐

  1. [LeetCode] 86. Partition List 划分链表

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  2. mysql instr()函数

    1)instr()函数的格式  (俗称:字符查找函数) 格式一:instr( string1, string2 )    /   instr(源字符串, 目标字符串) 格式二:instr( strin ...

  3. linux查看哪个进程占用磁盘IO

    方法一: $ iotop -oP 命令的含义:只显示有I/O行为的进程 测试结果: 方法二: $ pidstat -d 1 命令的含义:展示I/O统计,每秒更新一次 测试结果:

  4. [07]Go设计模式:过滤器模式(FilterPattern)

    目录 过滤器模式 一.简介 二.代码 三.参考链接 过滤器模式 一.简介 过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使 ...

  5. linux中安装python3.7

    linux中安装python3.7 1. 安装依赖包 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite- ...

  6. Servlet知识点小结

    Servlet: server applet * 概念:运行在服务器端的小程序 * Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则. * 将来我们自定义一个类,实 ...

  7. stm32F103片上串口USART1通信实验

    硬件说明:如原理图所示, 103的PA10 PA11分别接CP2102usb转串口芯片的TXD RXD引脚.CP2102芯片是将串口和电脑USB接口进行了转接,方便应用灵活. 片上串口驱动代码如下. ...

  8. LOJ2882 JOISC2014 两个人的星座 计算几何

    传送门 一件值得注意的事情是:平面上两个不相交的三角形一定会存在两条公切线 那么我们可以枚举三角形的公切线,计算有多少个三角形的公切线之一为该线,所有的答案除以2就是我们要求的答案. 考虑如何去计算有 ...

  9. JDK提供的原子类和AbstractQueuedSynchronizer(AQS)

    大致分成: 1.原子更新基本类型 2.原子更新数组 3.原子更新抽象类型 4.原子更新字段 import java.util.concurrent.atomic.AtomicInteger; impo ...

  10. oracel 查询语句

    1.以左边为显示表,从其他表查询关联的数据(多表查询) select a.*,b.name from da as a left join db as b on a.id = b.pid left jo ...