专栏文章

题解:P12024 [USACO25OPEN] It's Mooin' Time III B

P12024题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mini9kmz
此快照首次捕获于
2025/12/02 02:51
3 个月前
此快照最后确认于
2025/12/02 02:51
3 个月前
查看原文

思路

首先对于两个在区间 [l,r][l,r] 中的哞叫 (i,j,k1),(i,j,k2)(i,j,k_1),(i,j,k_2),如果 k1<k2k_1<k_2,那么显然后者更优。同理 (i1,j,k),(i2,j,k)(i_1,j,k),(i_2,j,k) 中如果 i1<i2i_1<i_2,那么前者更优。因此对于每次询问我们枚举小写字母 cc,只需要考虑 k[l,r]k\in[l,r]sk=cs_k=c 的最大 kk 和满足 i[l,r]i\in[l,r]sics_i\ne c 的最小 ii 即可。可以二分求出。那么此时我们选取的 jj 需要满足 j(i,k)j\in(i,k)sj=cs_j=c,可以发现 jj 越接近 i+k2\frac{i+k}{2},哞叫 sisjsks_is_js_k 的值 (kj)(ji)(k-j)(j-i) 越大。因此可以二分求出 jj。最后总复杂度 O(QlogN)O(Q\log N)

代码

CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
// #define DEBUG
#define FASTER_IO
int n,q;
int s[100005];
int mp[100005],mnp[26];
vector<int> pos[26];
int getnearest(const vector<int> &vec,int l,int r,int p) // get the nearest number of vec to p in [l,r]
{
    if(l>r)
        return -1;
    auto le=lower_bound(vec.begin(),vec.end(),l),ri=upper_bound(vec.begin(),vec.end(),r);
    if(ri<=le)
        return -1;
    else
    {
        if(p<*le)
            return *le;
        if(p>*(ri-1))
            return *(ri-1);
        auto rr=lower_bound(le,ri,p),ll=upper_bound(le,ri,p)-1;
        int lek=*ll,ril=*rr;
        if(p-lek<ril-p)
            return lek;
        else
            return ril;
    }
}
int getmax(const vector<int> &vec,int l,int r)
{
    return getnearest(vec,l,r,r+1);
}
int getmin(const vector<int> &vec,int l,int r)
{
    return getnearest(vec,l,r,l-1);
}
signed main()
{
    #ifdef FASTER_IO
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    #define endl "\n"
    #endif
    cin>>n>>q;
    for(int i=1;i<=n;i++)
    {
    	char c;
        cin>>c;
        s[i]=c-'a';
        pos[s[i]].push_back(i);
    }
    for(int i=0;i<26;i++)
        mnp[i]=n+1;
    for(int i=n;i>=1;i--)
    {
        mp[i]=n+1;
        for(int j=0;j<26;j++)
            if(j!=s[i])
                mp[i]=min(mp[i],mnp[j]);
        mnp[s[i]]=i;
    }
    while(q--)
    {
        int l,r;
        cin>>l>>r;
        long long ans=-1;
        for(int i=0;i<26;i++)
        {
            int mx=getmax(pos[i],l,r);
            if(mx==-1)
                continue;
            int p3=mx,p1=(s[l]==i?mp[l]:l);
            int p2=getnearest(pos[i],l,r,(p1+p3)/2);
            int p22=getnearest(pos[i],l,r,(p1+p3+1)/2);
            #ifdef DEBUG
            cout<<"p2="<<p2<<",p22="<<p22<<endl;
            #endif
            if(abs(p22-(p1+p3)/2.0)<abs(p2-(p1+p3)/2.0))
                p2=p22;
            if(p1<p2&&p2<p3)
            {
            	#ifdef DEBUG
	            cout<<"choose"<<p1<<","<<p2<<","<<p3<<endl;
	            #endif
	            ans=max(ans,1ll*(p3-p2)*(p2-p1));
        	}
        }
        cout<<ans<<endl;
    }
    return 0;
}
/*
12 1
abcabbacabac
1 12
*/

评论

0 条评论,欢迎与作者交流。

正在加载评论...