Substring of Sorted String

写篇题解纪念一下蒟蒻第一次赛时切出的 F 题。

题目简述

对一个字符串进行单点修改,区间判断操作。

修改操作为将一个字符修改为另一个,判断操作为判断区间是否是整个字符串升序排序后的字串。

思路分析

蒟蒻第一眼线段树,但刚开始没仔细看题,以为是判断区间是否升序排序,所以很快得到做法:

对于每个线段树上的节点,保存三个信息:区间最左端的字符 \(\text{lz}\),区间最右端的字符 \(\text{rz}\),区间是否升序排序 \(\text{is}\)。

合并时,我们按照如下方法合并:(记整个区间的编号为 \(\text{p}\),左区间的编号为 \(\text{lson}\),右区间的编号为 \(\text{rson}\)。)

lz[p]=lz[lson]
rz[p]=rz[rson]
is[p]=is[lson]&&is[rson]&&(rz[lson]<=ls[rson])

至于为什么这样合并是显然的。

但在蒟蒻写完交了一发后,发现 WA 了,仔细看题后发现是判断区间是否是整个字符串是否是整个字符串升序排序后的字串。

但在思考后,蒟蒻得到了一个做法:

在每个节点上额外维护一个数组 \(\text{cnt}\),\(\text{cnt}[i]\) 表示在这个整个区间内第 \(i\) 个小写字母出现的个数,合并时只需要对于枚举每一个字符相加就行。

在判断时,我们在升序排序的基础上,判断这个区间内除了最左端字符和最右端字符之外的字符出现次数是否等于整个字符串的该字符出现次数就可以了,这样是可以保证没有问题的。

时间复杂度为 \(O(26q\log n)\),虽然常数比 \(\log\) 还大,但不影响正确性。

注意事项

单点修改后记得将之前的位置清零。

注意下标的同步。

代码

放上丑陋的赛时代码:

#include <bits/stdc++.h>
using namespace std;
const int N=100100; int n,q,op,in1,in3;
char inp[N];//整个字符串
char in2[2];//输入的操作类型 struct STn{int l,r,is;char lz,rz;int cnt[30];};//线段树的节点
void merge(STn &res,STn a,STn b){//合并区间
res.lz=a.lz;
res.rz=b.rz;
res.is=(a.is&&b.is)&&(a.rz<=b.lz);//更新
for(int i=1;i<=26;i++)
res.cnt[i]=a.cnt[i]+b.cnt[i];//相加
}
struct ST{
STn a[N<<2];
void build(int p,int l,int r){
a[p].l=l;a[p].r=r;
if(a[p].l==a[p].r){a[p].lz=a[p].rz=inp[a[p].l];a[p].is=1;a[p].cnt[inp[a[p].l]-'a'+1]=1;return ;}//初始化
int mid=(a[p].l+a[p].r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
merge(a[p],a[p<<1],a[p<<1|1]);return ;
}
void change(int p,int x,char k){
if(a[p].l==a[p].r){a[p].cnt[a[p].lz-'a'+1]=0;a[p].lz=a[p].rz=k;a[p].cnt[k-'a'+1]=1;return ;}//单点修改后重置
int mid=(a[p].l+a[p].r)>>1;
if(x<=mid) change(p<<1,x,k);else change(p<<1|1,x,k);
merge(a[p],a[p<<1],a[p<<1|1]);return ;
}
STn ask(int p,int l,int r){
if(l<=a[p].l&&a[p].r<=r) return a[p];
int mid=(a[p].l+a[p].r)>>1;
if(r<=mid) return ask(p<<1,l,r);
if(l>mid) return ask(p<<1|1,l,r);
STn res;merge(res,ask(p<<1,l,r),ask(p<<1|1,l,r));//询问合并
return res;
}
}tree; int main(){
scanf("%d",&n);
scanf("%s",inp+1);
scanf("%d",&q);
tree.build(1,1,n);
while(q--){
scanf("%d",&op);
if(op==1){scanf("%d%s",&in1,in2+1);tree.change(1,in1,in2[1]);}
if(op==2){
scanf("%d%d",&in1,&in3);
STn res=tree.ask(1,in1,in3);
if(res.is){//前提是区间升序排序
int f=1;
for(int i=res.lz+1;i<=res.rz-1;i++)
if(res.cnt[i-'a'+1]!=tree.a[1].cnt[i-'a'+1]){//tree.a[1]就是整个字符串
f=0;break;
} //判断字符出现次数
puts(f?"Yes":"No");
}
else puts("No");
}
}
return 0;
}

Substring of Sorted String 题解的更多相关文章

  1. F - Substring of Sorted String

    题目链接 题解(树状数组) 我们维护两个树状数组,一个记录 \(1\sim i\) 中 \(s_i>s_{i+1}\)的数量,即逆序对数量,另一个记录 \(1\sim i\) 中 \(26\) ...

  2. LeetCode 1234. Replace the Substring for Balanced String

    原题链接在这里:https://leetcode.com/problems/replace-the-substring-for-balanced-string/ 题目: You are given a ...

  3. java用substring函数截取string中一段字符串

    在String中有两个substring()函数,如下: 一:String.substring(int start) 参数: start:要截取位置的索引 返回: 从start开始到结束的字符串 例如 ...

  4. [LeetCode]Longest Substring Without Repeating Characters题解

    Longest Substring Without Repeating Characters: Given a string, find the length of the longest subst ...

  5. LeetCode第[5]题(Java):Longest Palindromic Substring 标签:String、动态规划

    题目中文:求最长回文子串 题目难度:Medium 题目内容: Given a string s, find the longest palindromic substring in s. You ma ...

  6. 【leetcode】1234. Replace the Substring for Balanced String

    题目如下: You are given a string containing only 4 kinds of characters 'Q', 'W', 'E' and 'R'. A string i ...

  7. LeetCode longest substring without repeating characters 题解 Hash表

    题目 Given a string, find the length of the longest substring without repeating characters. Example 1: ...

  8. [LeetCode] Decode String 题解

    题目 题目 s = "3[a]2[bc]", return "aaabcbc". s = "3[a2[c]]", return " ...

  9. [LeetCode]Remove Duplicates from Sorted Array题解

    Remove Duplicates from Sorted Array: Given a sorted array, remove the duplicates in place such that ...

  10. Leetcode Find Minimum in Rotated Sorted Array 题解

    Leetcode Find Minimum in Rotated Sorted Array 题目大意: 对一个有序数组翻转, 就是随机取前K个数,移动到数组的后面,然后让你找出最小的那个数.注意,K有 ...

随机推荐

  1. 让golang程序生成coredump文件并进行调试

    今天讲讲怎么让golang程序生成coredump文件,并且进行调试的. 别看我写了不少golang的博客,其实我平时写c++的时间更多,所以也算和coredump是老相识了.core dump文件实 ...

  2. IP 地址斜杠后的数字和子网掩码

    目录 先上结论 IP 地址类型 ABC 类地址的划分 网络地址与广播地址 网络地址 广播地址 0.0.0.0 与 127.0.0.1 子网掩码 ABC 类 IP 地址最大网络范围与最大可用主机数 以 ...

  3. 聊聊Spring注解@Transactional失效的那些事

    一.前言 emm,又又又踩坑啦.这次的需求主要是对逾期计算的需求任务进行优化,现有的计算任务运行时间太长了.简单描述下此次的问题:在项目中进行多个数据库执行操作时,我们期望的是将其整个封装成一个事务, ...

  4. msvc C++编译链接

    C++编译链接 C++编译链接 静态库编译 C RunTimeLibrary 链接过程 动态库编译 场景问题加深理解 总结 静态库编译 C RunTimeLibrary C++是C的超集,C RunT ...

  5. Linux 安装:中文manpages

    Linux 中文man手册安装 bash 脚本 wget https://src.fedoraproject.org/repo/pkgs/man-pages-zh-CN/manpages-zh-1.5 ...

  6. 操作系统复习 MITS6.1810 lab util 记录

    lab util sleep 介绍:主要用来熟悉下环境以及代码结构. See kernel/sysproc.c for the xv6 kernel code that implements the ...

  7. 【更新】【解决中文文件名乱码】mac一键获取最新datagrid 2017.3注册码到剪贴板

    背景与前版实现请见: 前版原文 需要the unarchiver 解决中文文件名在mac上创建文件异常. 代码调整 IDEA_JIHUOMA_HOME="/tmp/idea-jihuoma& ...

  8. 更快的训练和推理: 对比 Habana Gaudi®2 和英伟达 A100 80GB

    通过本文,你将学习如何使用 Habana Gaudi2 加速模型训练和推理,以及如何使用 Optimum Habana 训练更大的模型.然后,我们展示了几个基准测例,包括 BERT 预训练.Stabl ...

  9. [kubernetes]二进制部署k8s集群

    0. 前言 采用二进制部署三主三工作节点的k8s集群,工作节点和Master节点共用服务器,因此只用到了三台服务器.master采用haproxy + keepalive实现高可用.实际生产环境中,建 ...

  10. Linux 身份验证被拒绝,登录失败解决

    解决方案: vim /etc/ssh/sshd_config 修改参数 基本参数: PermitRootLogin yes #允许root认证登录 PasswordAuthentication yes ...