JZOJ P5829 HZOI 20190801 A string 线段树
JZOJ P5829 A. string
题面:https://www.cnblogs.com/Juve/articles/11286476.html
考场上想起了排序这道题:https://www.cnblogs.com/Juve/p/11269638.html
n遍二分?
亲测TLE,0分
你暴力sort都有40分
当然这题不用这样
我们借鉴排序的思路
我们用线段树来完成操作,那么我们想线段树存什么,懒标记是什么
借鉴刚才那道题,我们将节点信息和懒标记合二为一
设tr[k].val,如果k管辖的区间里的字母都是同一个字母,则tr[k].val就是那个字母,否则tr[k].val=0,
这样十分方便维护:
down:
if(!tr[k].val) return ;
tr[k<<1].val=tr[k<<1|1].val=tr[k].val;
up:
if(tr[k<<1].val==tr[k<<1|1].val)
tr[k].val=tr[k<<1].val;
我们每次对于一次排序[L,R],查询[L,R],中26个字母出现的次数cnt[i],
实现:
if(opl<=l&&r<=opr&&tr[k].val){
cnt[tr[k].val]+=(r-l+1);
return ;
}
如果升序,就把[L,R]中前cnt[a]修改成a,接下来cnt[b]修改成b,。。。。。。
降序就反过来
最后输出也是一遍线段树dfs,然后。。。其实没什么了
来代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define MAXN 100005
#define re register
using namespace std;
int n,m,a[MAXN],cnt[28];
char ch[MAXN]
struct Segtree{
int l,r,val;
}tr[MAXN<<2];
void down(int k,int data){
if(!tr[k].val) return ;
tr[k<<1].val=tr[k<<1|1].val=tr[k].val;
tr[k].val=data;
}
void build(int k,int l,int r){
tr[k].l=l,tr[k].r=r;
if(l==r){
tr[k].val=a[l];
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
if(tr[k<<1].val==tr[k<<1|1].val)
tr[k].val=tr[k<<1].val;
}
void get_cnt(int k,int opl,int opr){
int l=tr[k].l,r=tr[k].r;
if(opl<=l&&r<=opr&&tr[k].val){
cnt[tr[k].val]+=(r-l+1);
return ;
}
down(k,tr[k].val);
int mid=(l+r)>>1;
if(opl<=mid) get_cnt(k<<1,opl,opr);
if(opr>mid) get_cnt(k<<1|1,opl,opr);
}
void change(int k,int opl,int opr,int data){
if(tr[k].val==data) return ;
int l=tr[k].l,r=tr[k].r;
if(opl<=l&&r<=opr){
tr[k].val=data;
return ;
}
down(k,0);
int mid=(l+r)>>1;
if(opl<=mid) change(k<<1,opl,opr,data);
if(opr>mid) change(k<<1|1,opl,opr,data);
if(tr[k<<1].val==tr[k<<1|1].val)
tr[k].val=tr[k<<1].val;
}
void print(int k){
if(tr[k].val){
int l=tr[k].l,r=tr[k].r;
for(int i=l;i<=r;i++)
putchar(tr[k].val-1+'a');
return ;
}
print(k<<1),print(k<<1|1);
}
int main(){
scanf("%d%d",&n,&m);
scanf("%s",ch+1);
for(re int i=1;i<=n;i++)
a[i]=ch[i]-'a'+1;
build(1,1,n);
for(re int i=1,x,l,r;i<=m;i++){
scanf("%d%d%d",&l,&r,&x);
memset(cnt,0,sizeof(cnt));
get_cnt(1,l,r);
if(x==0){
for(re int j=26;j>=1;j--){
change(1,l,l+cnt[j]-1,j);
l+=cnt[j];
}
}else{
for(re int j=1;j<=26;j++){
change(1,l,l+cnt[j]-1,j);
l+=cnt[j];
}
}
}
print(1);
puts("");
return 0;
}
JZOJ P5829 HZOI 20190801 A string 线段树的更多相关文章
- 考试题string——线段树。
string[题目描述]给定一个由小写字母组成的字符串 s.有 m 次操作,每次操作给定 3 个参数 l,r,x.如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]降序 ...
- string [线段树优化桶排]
题意大概是给你一个字符串,1e5次修改,每次给一个区间升序排列或降序排列,最后输出这个字符串; 其实是个挺裸的线段树优化题;但是我没有意识去结合桶排,扑该..... 首先 1.40分算法 O(NMlo ...
- hdu3973 AC's String 线段树+字符串hash
题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3973/ 题意是:给出一个模式串,再给出一些串组成一个集合,操作分为两种,一种是替换模式串中的一个字符,还有一种是 ...
- 【模拟8.01】string(线段树)
因为题中只有a-z,所以区间中大量字母都是重复的,我们不妨利用桶的性质. 开一棵树,里面维护当前区间内的相同元素,若区间内元素不同,则为零 每次升序操作就先查询一遍区间,用桶将每个区间的a-z元素统计 ...
- HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...
- HDU 6096 String 排序 + 线段树 + 扫描线
String Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others) Problem De ...
- [jzoj 5662] 尺树寸泓 解题报告 (线段树+中序遍历)
interlinkage: https://jzoj.net/senior/#contest/show/2703/1 description: solution: 发现$dfs$序不好维护 注意到这是 ...
- [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)
题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...
- HDU - 3973 AC's String(Hash+线段树)
http://acm.hdu.edu.cn/showproblem.php?pid=3973 题意 给一个词典和一个主串.有两种操作,查询主串某个区间,问这主串区间中包含多少词典中的词语.修改主串某一 ...
随机推荐
- java中的break continue
break语句 在任何循环语句的主体部分,均可用break控制循环的流程.break用于强行退出循环,不执行循环中剩余的语句.(break语句也在switch语句中使用) public class B ...
- 模拟MySQL命令
staff_table 1,Alex Li,22,13651054608,IT,2013-04-01 2,Jack Wang,30,13304320533,HR,2015-05-03 3,Rain L ...
- thinkphp 模版引擎
系统支持原生的PHP模板,而且本身内置了一个基于XML的高效的编译型模板引擎,系统默认使用的模板引擎是内置模板引擎,关于这个模板引擎的标签详细使用可以参考模版引擎部分. 内置的大理石平台检定规程模板引 ...
- 0921CSP-S模拟测试赛后总结
倒数第一祭. 感觉T3数据范围50可以qj一下.于是押了T3. 然后两个小时调我4.1k的bfs.最后调出来了发现策略错了.十分绝望. T120分吊住了.十分难过.倒数第一了.还是实力不行. 不应该押 ...
- iOS中消息的传递机制
本文中,会经常提及接收者[recipient]和发送者[sender].在消息传递机制中具体是什么意思,我们可以通过一个示例来解释:一个table view是发送者,而它的delegate就是接收者. ...
- vue+el-menu+vue-router实现动态导航条
导航栏组件template <template> <div class="sidebar"> <el-menu unique-opened :defa ...
- Django框架中session存储到redis中的配置
本文链接:https://blog.csdn.net/linqunbin/article/details/94786313————————————————版权声明:本文为CSDN博主「linqunbi ...
- nvelocity的Foreach 中使用DataTable数据
原文:nvelocity的Foreach 中使用DataTable数据 tripDetailList是一个DataTable类型的数据,Logo.TripTypeName.TipTypePrice等为 ...
- 2019-11-12-浅谈-Windows-桌面端触摸架构演进
title author date CreateTime categories 浅谈 Windows 桌面端触摸架构演进 lindexi 2019-11-12 14:37:31 +0800 2019- ...
- linux 2.6 内核的移植
内核移植过程 下载 linux 内核 从 http://www.kernel.org/pub/linux/kernel/v2.6/linux2.6.14.1.tar.bz2 下载 linux2 ...