AtCoder Beginner Contest 381-E

Problem

一个长度为奇数、最中间的那个字符是 /、左边所有字符都是都是 1、右边所有字符都是 2 的字符串被称为11/22 字符串

更加严谨的定义:

当一个字符串 \(T\) 满足以下所有条件时,它被称为11/22 字符串

  • \(|T|\) 是奇数。这里, \(|T|\) 表示 \(T\) 的长度。
  • 从第 \(1\) 到第\((\frac{|T|+1}{2} - 1)\) 个字符都是 1
  • 第 \((\frac{|T|+1}{2})\) 个字符是/
  • 从第 \((\frac{|T|+1}{2} + 1)\) 到第 \(|T|\) 的字符都是 2

例如,11/22111/222/是 11/22 字符串,但11221/22211/22222/11/2/2/211则不是。

给定由12/组成的字符串 \(S\) ,\(|S|=N\)。有 \(Q\) 次询问:给定 \(L\) 和 \(R\),设 \(T\) 是 \(S\) 的从第 \(L\) 个字符到第 \(R\) 个字符组成的子串。请找出 \(T\) 的最长子序列使得该子序列是一个 11/22 字符串。如果不存在这样的子序列,则打印 "0"。

Constraints

  • \(1 \leq N \leq 10^5\)
  • \(1 \leq Q \leq 10^5\)
  • \(S\) is a string of length \(N\) consisting of 1, 2, and /.
  • \(1 \leq L \leq R \leq N\)
  • \(N\), \(Q\), \(L\), and \(R\) are integers.

Solution

考虑预处理出所有/的位置,记作 \(pos_i\)。

使用前缀和后缀和计算“每一个字符之前有多少个1”和“每一个字符之后有多少个2”,分别记作 \(left1_i\) 和 \(right2_i\)。

对于每次询问,一个简单暴力的算法就是,枚举在该区间内的所有/,并看看其左右分别有多少个12,则选择该/作为11/22子串的中间的那个/能够找出的最长子序列长度为

\[\begin{align}
ans_i=\min\{left1_{pos_i}-left1_{L},right2_{pos_i}-right2_{R}\} \quad L\le pos_i \le R
\end{align}
\]

即可以利用预处理的信息,在\(O(1)\)的时间复杂度内计算出选择某个/时的答案。

并且可以通过二分 \(pos_i\) 来得到需要枚举的 \(i\) 的范围。

但是这样还是需要枚举 \([L,R]\) 内的所有/,如果/很多就寄了。

观察上式可以发现,随着 \(pos_i\) 增大,\(left1_{pos_i}-left1_L\) 单调递增,\(right2_{pos_i}-right2_R\) 单调递减。\(\min\{增函数,减函数\}\) 一定是一个开口向下的单峰函数,所以可以使用三分来确定最佳的 \(pos_i\)。

Code

#define N 1000010

int left1[N],left2[N],right1[N],right2[N];
int n,q;
string str;
int pos[N],cnt;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.precision(10);
int t=1;
// cin>>t;
while(t--)
{
cin>>n>>q;
cin>>str;
str=" "+str;
// pos[++cnt]=0;
for(int i=1;i<=n;i++)
{
if(str[i]=='/')
{
pos[++cnt]=i;
}
}
pos[++cnt]=n+1;
int pre1=0,pre2=0;
for(int i=1;i<=n;i++)
{
left1[i]=pre1;
left2[i]=pre2;
if(str[i]=='1') pre1++;
if(str[i]=='2') pre2++;
}
pre1=pre2=0;
for(int i=n;i>=1;i--)
{
right1[i]=pre1;
right2[i]=pre2;
if(str[i]=='1') pre1++;
if(str[i]=='2') pre2++;
} while(q--)
{
int a,b,ans=0;cin>>a>>b;
// 确定左右边界,即找到最远的一对杠但是在[a,b]之内
int l=lower_bound(pos+1,pos+cnt+1,a)-pos;
int r=upper_bound(pos+1,pos+cnt+1,b)-pos-1;
// DEBUG1(l);
// DEBUG1(r);
while(l+3000<r)
{
int mid1=l+(r-l)/3;
int mid2=r-(r-l)/3;
int p1=pos[mid1],p2=pos[mid2];
int s1=min(left1[p1]-left1[a],right2[p1]-right2[b]);
int s2=min(left1[p2]-left1[a],right2[p2]-right2[b]);
if(s1<s2)
{
l=mid1;
}
else{
r=mid2;
}
}
for(int i=l;i<=r;i++)
{
int p=pos[i];
if(str[p]=='/')
{
// cout<<"calc "<<i<<endl;
// cout<<min(left1[p]-left1[a],right2[p]-right2[b])<<endl;
ans=max(ans,1+2*min(left1[p]-left1[a],right2[p]-right2[b]));
}
}
cout<<ans<<endl;
} }
return 0;
}

AtCoder Beginner Contest 381-E的更多相关文章

  1. AtCoder Beginner Contest 100 2018/06/16

    A - Happy Birthday! Time limit : 2sec / Memory limit : 1000MB Score: 100 points Problem Statement E8 ...

  2. AtCoder Beginner Contest 052

    没看到Beginner,然后就做啊做,发现A,B太简单了...然后想想做完算了..没想到C卡了一下,然后还是做出来了.D的话瞎想了一下,然后感觉也没问题.假装all kill.2333 AtCoder ...

  3. AtCoder Beginner Contest 053 ABCD题

    A - ABC/ARC Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Smeke has ...

  4. AtCoder Beginner Contest 136

    AtCoder Beginner Contest 136 题目链接 A - +-x 直接取\(max\)即可. Code #include <bits/stdc++.h> using na ...

  5. AtCoder Beginner Contest 137 F

    AtCoder Beginner Contest 137 F 数论鬼题(虽然不算特别数论) 希望你在浏览这篇题解前已经知道了费马小定理 利用用费马小定理构造函数\(g(x)=(x-i)^{P-1}\) ...

  6. AtCoder Beginner Contest 076

    A - Rating Goal Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Takaha ...

  7. AtCoder Beginner Contest 079 D - Wall【Warshall Floyd algorithm】

    AtCoder Beginner Contest 079 D - Wall Warshall Floyd 最短路....先枚举 k #include<iostream> #include& ...

  8. AtCoder Beginner Contest 064 D - Insertion

    AtCoder Beginner Contest 064 D - Insertion Problem Statement You are given a string S of length N co ...

  9. AtCoder Beginner Contest 075 D - Axis-Parallel Rectangle【暴力】

    AtCoder Beginner Contest 075 D - Axis-Parallel Rectangle 我要崩溃,当时还以为是需要什么离散化的,原来是暴力,特么五层循环....我自己写怎么都 ...

  10. AtCoder Beginner Contest 075 C bridge【图论求桥】

    AtCoder Beginner Contest 075 C bridge 桥就是指图中这样的边,删除它以后整个图不连通.本题就是求桥个数的裸题. dfn[u]指在dfs中搜索到u节点的次序值,low ...

随机推荐

  1. [第三章]ABAQUS CM插件中文手册

    ABAQUS Composite Modeler User Manual(zh-CN) Dassault Systèmes, 2018 注: 源文档的交叉引用链接,本文无效 有些语句英文表达更易理解, ...

  2. dig命令命令常见用法

    域名结构 主机名.次级域名.域名.根域名 host. sld .tld .root 几种常见的解析类型 A记录 CNAME txt记录 dig命令命令常见用法 dig,"domain inf ...

  3. Web前端入门第 14 问:HTML 语义化是什么?

    HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 语义化:通俗地说,就是让机器可以理解编写出来的 HTML 代码.比如:搜索引擎.屏幕阅读器等. 非语义化写法 网 ...

  4. 迅速理解 LCS 最长公共子序列问题

    在算法与数据结构的经典问题中,最长公共子序列(Longest Common Subsequence,简称 LCS)问题占据着重要的地位.给定两个序列,我们需要找到它们最长的公共子序列,而子序列要求保持 ...

  5. Golang windows下 交叉编译

    前言 在进行Go开发的时候,go env 可以设置Go的环境变量信息 GOOS 的默认值是我们当前的操作系统, 如果 windows,linux,注意 mac os 操作的上的值是darwin. GO ...

  6. Effective Java理解笔记系列-第1条-何时考虑用静态工厂方法替代构造器?

    为什么写这系列博客? 在阅读<Effective Java>这本书时,我发现有许多地方需要仔细认真地慢慢阅读并且在必要时查阅相关资料才能彻底搞懂,相信有些读者在阅读此书时也有类似感受:同时 ...

  7. 【SpringCloud】SpringCloud Alibaba入门简介

    SpringCloud Alibaba入门简介 why会出现SpringCloud alibaba Spring Cloud Netflix项目进入到维护模式 SpringCloud Netflix ...

  8. 【Ubuntu】安装OpenSSH启用远程连接

    [Ubuntu]安装OpenSSH启用远程连接 零.安装软件 使用如下代码安装OpenSSH服务端: sudo apt install openssh-server 壹.启动服务 使用如下代码启动Op ...

  9. 【视频编辑】Pr视频编辑软件导出的视频声音有一段会变大怎么解决

    导出视频后为什么有段声音会突然变大? 也就是可能存在编辑器导出的时候有自动增益声音的行为. 具体描述: 工程文件里我没动过声音,工程文件里听也是很正常的,但是导出后有一小段音乐会突然变大(存在自动增益 ...

  10. Docker 实用镜像

    实用镜像 nginx-proxy nginx-proxy sets up a container running nginx and docker-gen. ...