At381 E - 11/22 Subsequence
E.11/22 Subsequence
题意简述
定义1122字符串,当一个字符串长度是奇数,中心为'/'字符,左边都是1,右边都是2,这个字符串是1122字符串,现在给你一个字符串和Q组查询,每组查询划定一个区间\([L,R]\),对于每一个询问要求求出这个字符串第 \(L\) 位到第 \(R\) 位最长1122字符串的长度。
解题思路
直接暴力求解是 \(O(n·n·q)\) 的复杂度,肯定会超时,考虑对于维护'/'位置以及'/'字符左边极长的1的个数 \(num1\) 和右边极长的2的个数 \(num2\),这个'/'对答案的贡献就是min(num1,num2)*2+1。对于左边极长的1的个数和右边极长的2的个数可以用前缀和维护,那么我们要求解的问题就转化到了如何在一个[L,R]上的区间快速找到'/'的所有合法位置,那么我们可以预处理出所有合法的'/'位置数组,查询时对数组进行二分查找
AC code
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll inf=1e18;
int main(){
cin.tie(0)->ios::sync_with_stdio(false);
int n,q;cin>>n>>q;
string s;
cin>>s;
vector<int>pre1(n+1);
vector<int>pre2(n+1);
vector<int>m(1);
for(int i=0;i<s.size();i++){
pre1[i+1]=pre1[i]+(s[i]=='1');
pre2[i+1]=pre2[i]+(s[i]=='2');
if(s[i]=='/') m.push_back(i+1);
}
for(int i=1;i<=q;i++){
int L,R;cin>>L>>R;
int l=1,r=m.size()-1;
int ans=0;
while(l<=r){
int mid=l+r>>1;
if(m[mid]<L) l=mid+1;
else if(m[mid]>R) r=mid-1;
else{
int num1=pre1[m[mid]]-pre1[L-1];
int num2=pre2[R]-pre2[m[mid]-1];
ans=max(ans,2*min(num1,num2)+1);
if(num1<=num2) l=mid+1;
else r=mid-1;
}
}
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号