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;
}
posted @ 2025-05-25 19:20  usedchang  阅读(29)  评论(0)    收藏  举报