[CSP-S模拟测试]:string(线段树)
题目描述
给定一个由小写字母组成的字符串$s$。
有$m$次操作,每次操作给定$3$个参数$l,r,x$。
如果$x=1$,将$s[l]~s[r]$升序排序;
如果$x=0$,将$s[l]~s[r]$降序排序。
你需要求出最终序列。
输入格式
第一行两个整数$n,m$。
第二行一个字符串$s$。
接下来m行每行三个整数$l,r,x$。
输出格式
一行一个字符串表示答案。
样例
样例输入
5 2
cabcd
1 3 1
3 5 0
样例输出
abdcc
数据范围与提示
对于$40\%$的数据,$n,m\leqslant 1,000$。
对于$100\%$的数据,$n,m\leqslant 100,000$。
题解
看到这道题,我就想到了:[BZOJ4552]:[Tjoi2016&Heoi2016]排序(桶排序)。
然而,那道题我使用桶排序卡过的,时限还是$6,000ms$,所以我当场懵逼,线段树是肯定看出来了,但是不知道该怎么操作……
打题一定要打正解挖~
$40\%$算法:
直接用$sort$搞就好了,重载一下运算符,我觉得我说的每一句都是废话……
桶排一分也不能多拿(万恶的出题人)。
时间复杂度:
$\Theta(m\times n)$(桶排序)。
$\Theta( m\times n\log n)$(快排)。
期望得分:$40$分。
$100\%$算法:
因为这道题串中只有26个字母,所以就好说多了,用线段树维护区间内$a~z$的个数,每次修改拆成26个修改就行了。
时间复杂度:$\Theta(26\times m\times \log n)$。
期望得分:$100$分。
代码时刻
$40\%$算法:
#include<bits/stdc++.h>
using namespace std;
int n,m,l,r;
bool x;
int a[100001];
char ch[100001];
int t[50];
int st,ed;
void change1()
{
register int maxn=0,minn=20020923,lft=l;
for(int i=l;i<=r;i++)
{
t[a[i]]++;
maxn=max(maxn,a[i]);
minn=min(minn,a[i]);
}
for(register int i=minn;i<=maxn;i++)
while(t[i])
{
a[lft++]=i;
t[i]--;
}
}
void change2()
{
int maxn=0,minn=20020923,lft=l;
for(register int i=l;i<=r;i++)
{
t[a[i]]++;
maxn=max(maxn,a[i]);
minn=min(minn,a[i]);
}
for(register int i=maxn;i>=minn;i--)
while(t[i])
{
a[lft++]=i;
t[i]--;
}
} int main()
{
st=clock();
scanf("%d%d%s",&n,&m,ch+1);
for(register int i=1;i<=n;i++)
a[i]=ch[i]-'a'+1;
while(m--)
{
scanf("%d%d%d",&l,&r,&x);
if(x)change1();
else change2();
}
for(register int i=1;i<=n;i++)
printf("%c",(char)a[i]+'a'-1);
return 0;
}
$100\%$算法:
#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
int n,m;
char ch[100001];
int tr[400001];
int flag[30];
void pushup(int x){if(tr[L(x)]==tr[R(x)])tr[x]=tr[L(x)];}
void pushdown1(int x){if(tr[x])tr[L(x)]=tr[R(x)]=tr[x];}
void pushdown2(int x){if(tr[x])tr[L(x)]=tr[R(x)]=tr[x];tr[x]=0;}
void build(int x,int l,int r)
{
if(l==r){tr[x]=ch[l]-'a'+1;return;}
int mid=(l+r)>>1;
build(L(x),l,mid);
build(R(x),mid+1,r);
pushup(x);
}
void ask(int x,int l,int r,int L,int R)
{
if(r<L||R<l)return;
if(L<=l&&r<=R&&tr[x]){flag[tr[x]]+=r-l+1;return;}
int mid=(l+r)>>1;
pushdown1(x);
ask(L(x),l,mid,L,R);
ask(R(x),mid+1,r,L,R);
}
void change(int x,int l,int r,int L,int R,int v)
{
if(r<L||R<l)return;
if((L<=l&&r<=R)||tr[x]==v){tr[x]=v;return;}
int mid=(l+r)>>1;
pushdown2(x);
change(L(x),l,mid,L,R,v);
change(R(x),mid+1,r,L,R,v);
pushup(x);
}
void print(int x,int l,int r)
{
if(tr[x]){for(int i=l;i<=r;i++)printf("%c",(char)tr[x]+'a'-1);return;}
int mid=(l+r)>>1;
print(L(x),l,mid);
print(R(x),mid+1,r);
}
int main()
{
scanf("%d%d%s",&n,&m,ch+1);
build(1,1,n);
while(m--)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
memset(flag,0,sizeof(flag));
ask(1,1,n,l,r);
if(x)for(int i=1;i<=26;i++){change(1,1,n,l,l+flag[i]-1,i);l+=flag[i];}
else for(int i=26;i>=1;i--){change(1,1,n,l,l+flag[i]-1,i);l+=flag[i];}
}
print(1,1,n);
return 0;
}
rp++
[CSP-S模拟测试]:string(线段树)的更多相关文章
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】
题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...
- [CSP-S模拟测试]:影魔(树状数组+线段树合并)
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
- 【NOIP模拟】board(线段树维护二进制,树序号化为二进制)
题目背景 SOURCE:NOIP2016-RZZ-2 T3 题目描述 给出这样一棵“二叉树”: 每个节点有左右两个儿子,并如下定义每个节点的高度:假设父亲节点的高度为 h ,那么他的两个儿子的节点的高 ...
- BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分
题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...
- 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)
传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码
- 2018.06.29 NOIP模拟 旅馆(线段树)
旅馆 [问题描述] OIEROIEROIER 们最近的旅游计划,是到长春净月潭,享受那里的湖光山色,以及明 媚的阳光.你作为整个旅游的策划者和负责人,选择在潭边的一家著名的旅馆住 宿.这个巨大的旅馆一 ...
- 2018.06.29 NOIP模拟 排列(线段树)
排列(premu.cpp) [题目描述] 对于一个 1 到 n 的排列,逆序数的定义为:排列中第 i 位 ai的逆序数就是 a1-ai-1中比 ai大的数的个数.另外用 pi表示 a1,-,ai的逆序 ...
- 考试题string——线段树。
string[题目描述]给定一个由小写字母组成的字符串 s.有 m 次操作,每次操作给定 3 个参数 l,r,x.如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]降序 ...
随机推荐
- SpringBoot项目启动时执行初始化操作
SpringBooot中的CommandLineRunner接口会在所有Spring Beans初始化之后,SpringApplication.run()之前执行. 1.添加pom引用 <?xm ...
- [19/09/08-星期日] Python的几个概念和语法
一.表达式.语句.程序.函数 1.表达式 就是一个类似于数学公式的东西 ,比如:10 + 5 8 - 4:表达式一般仅仅用了计算一些结果,不会对程序产生实质性的影响 如果在交互模式中输入一个表达式,解 ...
- CentOS 7安装Python 2.6(与已有版本共存)
1. 安装需要用到的包 yum install -y zlib-devel bzip2-devel openssl-devel xz-libs wget 2. 下载 Python 2.6.8 版本 w ...
- 这款多线程中间件,吊打 Redis!
Java技术栈 www.javastack.cn 优秀的Java技术公众号 今天给大家介绍的是KeyDB,KeyDB项目是从redis fork出来的分支.众所周知redis是一个单线程的kv内存存储 ...
- JS中同步与异步
不讲过多定义,举两个例子说明下 例一: console.log(100); setTimeout(function(){ console.log(200); },1000); console.log( ...
- Widget代码讲解
参考:https://zhuanlan.zhihu.com/p/28225011 QT版本为5.12.4 1.main.cpp #include "widget.h" #inclu ...
- 嘉馨学姐又双叒叕来吃包子了 QDUOJ 模拟 尺度法
嘉馨学姐又双叒叕来吃包子了 QDUOJ 模拟 尺度法 点我进入OJ题目详情 题意 给你一串数,让你求长度最长的子串,这个字串满足里面没有重复出现的数字. 解题思路 使用一个标记数组,来标记每个数的第一 ...
- python列表,字典,集合
初识模块 import sys print(sys.path)#查看化境变量 print(sys.argv)#查看文件的相对路径,但是在pachrm中 会自动转为绝对路径 import os #os. ...
- Cypher 语句实战
Cypher 语句实战 下载和安装 Neo4j windows 桌面版- 环境设置 https://www.w3cschool.cn/neo4j/neo4j_exe_environment_setup ...
- HTTPS和HTTP的区别,http协议的特征
http协议传输的数据都是没有经过加密的,也就是明文,所以http用于传输数据并不安全.而https是是使用了ssl(secure socket layer)协议+http协议构成的可加密传输,身份认 ...