ABC381E题解

原题

题目描述

この問題における 11/22 文字列の定義は A 問題および C 問題と同じです。

文字列 T が以下の条件を全て満たすとき、 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/22, 111/222, / は 11/22 文字列ですが、1122, 1/22, 11/2222, 22/11, //2/2/211 はそうではありません。

1, 2, / からなる長さ N の文字列 S が与えられるので、 Q 個のクエリを処理してください。

各クエリでは L , R が与えられます。 S L 文字目から R 文字目までからなる (連続な) 部分文字列を T としたとき、 11/22 文字列であるような T (連続とは限らない) 部分列の長さの最大値を求めてください。そのような部分列が存在しないときは 0 を出力してください。

输入格式

入力は以下の形式で標準入力から与えられる。ここで \\mathrm{query}_i i 番目のクエリを意味する。

N Q S \\mathrm{query}_1 \\mathrm{query}_2 \\vdots \\mathrm{query}_Q

各クエリは以下の形式で与えられる。

L R

输出格式

Q 行出力せよ。 i 行目には i 番目のクエリへの答えを出力せよ。

输入输出样例 #1

输入 #1

复制代码
12 5
111/212/1122
1 7
9 12
3 6
4 10
1 12

输出 #1

复制代码
5
0
3
1
7

说明/提示

制約

  • 1\\ \\leq\\ N\\ \\leq\\ 10\^5
  • 1\\ \\leq\\ Q\\ \\leq\\ 10\^5
  • S 1, 2, / からなる長さ N の文字列
  • 1\\ \\leq\\ L\\ \\leq\\ R\\ \\leq\\ N
  • N,\\ Q,\\ L,\\ R は整数

Sample Explanation 1

1 番目のクエリについて、 S 1 文字目から 7 文字目からなる部分文字列は 111/212 です。この文字列は 11/22 を部分列として含み、これは 11/22 文字列であるような部分列として最大です。よって答えは 5 です。 2 番目のクエリについて、 S 9 文字目から 12 文字目からなる部分文字列は 1122 です。この文字列は 11/22 文字列であるような部分列を含まないので、答えは 0 です。

思路

可以发现对于任意一条杠,要想使对于这条杠最大,是直接将左边的全部 1 1 1 与右边全部的 2 2 2 取最小 × 2 + 1 \times2+1 ×2+1。

那么我们可以对 1 1 1 的个数与 2 2 2 的个数求一个前缀和。然后用二分对每一次询问求最左边的杠与最右边的杠,然后再用二分求最大。再来说一下求值的二分的具体方法。可以发现,如果 1 1 1 的个数少,肯定尽量往后靠,使得平均。 2 2 2 少时方法也一样,即往前靠,使得平均。我的写法是把三个二分和在一起,就不多介绍了。

Code

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,m,gang[1145140],sum1[1145140],sum2[1145140],id;
string s;
int main(){
	cin>>n>>m;
	cin>>s;
	s=' '+s;
	for(int i=1;i<=n;i++){
		if(s[i]=='/'){
			id++;
			gang[id]=i;
		}
		sum1[i]=sum1[i-1]+(s[i]=='1');
		sum2[i]=sum2[i-1]+(s[i]=='2');
	}
	while(m--){
		int l,r;
		cin>>l>>r;
		int li=1,ri=id,ans=0;
		while(li<=ri){
			int mid=(li+ri)/2;
			if(gang[mid]<l){
				li=mid+1;
				continue;
			}
			if(gang[mid]>r){
				ri=mid-1;
				continue;
			}
			int p1=sum1[gang[mid]]-sum1[l-1];
			int p2=sum2[r]-sum2[gang[mid]-1];
			if(p1<=p2){
				li=mid+1;
			}
			else{
				ri=mid-1;
			}
			ans=max(ans,2*min(p1,p2)+1);
		} 
		cout<<ans<<endl;
	}
	return 0;
}
相关推荐
超爱笑嘻嘻17 分钟前
shared_ptr八股收集 C++
c++
我想进大厂36 分钟前
图论---朴素Prim(稠密图)
数据结构·c++·算法·图论
我想进大厂41 分钟前
图论---Bellman-Ford算法
数据结构·c++·算法·图论
AIGC大时代43 分钟前
高效使用DeepSeek对“情境+ 对象 +问题“型课题进行开题!
数据库·人工智能·算法·aigc·智能写作·deepseek
光而不耀@lgy1 小时前
C++初登门槛
linux·开发语言·网络·c++·后端
啊丢_1 小时前
C++——Lambda表达式
开发语言·c++
CODE_RabbitV1 小时前
【深度强化学习 DRL 快速实践】近端策略优化 (PPO)
算法
Wendy_robot2 小时前
【滑动窗口+哈希表/数组记录】Leetcode 438. 找到字符串中所有字母异位词
c++·算法·leetcode
程序员-King.2 小时前
day49—双指针+贪心—验证回文串(LeetCode-680)
算法·leetcode·贪心算法·双指针
转基因3 小时前
Codeforces Round 1020 (Div. 3)(题解ABCDEF)
数据结构·c++·算法