题解 P7333【[JRKSJ R1] JFCA】

T1 JFCA

Subtask 1

这个 Subtaskn103 ,暴力 O(n2) 向左右拓展即可,但是由于没有 O2,只能通过数据点 14 数据点(数据点 4 可极限通过),期望得分 20.

Subtask 2

采用捆绑测试,105 的数据可以想到要用 O(nlogn) 的算法。

于是我们可以想到二分,但是 aj 没有单调性。于是我们可以维护区间最大值,满足单调性。

由于题目说这是一个环,我们可以使用分类讨论或者断环为链,这篇题解主要讲断环为链。

我们将每个数存 3 遍,即 ai+n+n=ai+n=ai.

定义 f(i,j)=maxk=ijak,我们设当前处理的是序号为 i 的数,则 check(x)=max(f(ix,i1),f(i+1,i+x))

我们对于i+n 二分一次即可。

注意事项:

  • 1.断环为链时,我们复制 3 遍的原因是处理较后的数时可能会造成数组越界错误。
  • 2.我们可以使用 ST表 平衡复杂度到 nlogn,也可以使用其他数据结构如线段树做到 nlog2n 的复杂度。
  • 3.由于 ij,求区间最大值时不能直接算 f(ix,i+x)

接下来就可以愉快的二分了,不理解的和剩余的内容可以结合代码理解。

std:

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
int n,m,st[N][30],lg[N];
namespace IO{
    //read(),write()
}using namespace IO;
inline int query(int l,int r){
    int q=lg[r-l+1];
    return max(st[l][q],st[r-(1<<q)+1][q]);
}
inline int ef(int x,int i){//二分
    int l=1,r=n;
    while(l<r){
        int mid=l+r>>1;
        if(max(query(i-mid,i-1),query(i+1,i+mid))>=x){
            r=mid;
        }else{
            l=mid+1;
        }
    }
    return l==n?-1:l;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){//断环为链
        st[i][0]=st[i+n][0]=st[i+n+n][0]=read();
    }
    for(int i=2;i<=n+n+n;i++){
        lg[i]=lg[i>>1]+1;
    }
    int ln=lg[n+n+n];
    for(int i=1;i<=ln;i++){//ST表预处理
        for(int j=1;j+(1<<i)-1<=n+n+n;j++){
            st[j][i]=max(st[j][i-1],st[j+(1<<i-1)][i-1]);
        }
    }
    for(int i=1;i<=n;i++){
        int b=read();
        int a2=ef(b,i+n);
        write(a2);
        out[len++]=' ';
    }
    fwrite(out,1,len,stdout);
    return 0;
}

这道题作为 T1 还是很水的,后面的题就很毒瘤了。

感谢大家参与这场比赛!

posted @   ffffyc  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示