题解 P7333 [JRKSJ R1] JFCA

原题

一道不难的题目。

题意已经很明确了。我们发现数据范围是 1n105,可以想到正解是一个 O(nn)O(nlogn) 的做法。

题解

我们要找到与 x 距离最近的 i,显然是按从 x 递增和递减两个方向去比较。复杂度劣的主要原因是比较很多不满足条件的数,即 ai 的值比 bx 小。

为了优化复杂度,我们维护一个区间内 ai 最大值,如果区间最大值比 bx 小,那整个区间都不会有符合题意的 ai,大大减少了比较次数。

但因为这是一个环,为了断环成链,需要开三倍空间,方便处理左右边界,并将原来的 [1,n] 放到 [n+1,n+n] 内处理,同时还有个小细节,即特判当 fx=n 时,这说明 x 绕了 n 个数回到了 x,此时将 fx1

容易想到分块。

对于 x 所在的块内,直接暴力枚举块边。然后像原来一样,按距 x 的距离递增比较每个块,若块内最大值大于 bx,就继续按距 x 的距离递增比较每个数,找到距 x 最近的 i 使 aibx

时间复杂度为 O(nn),但因为对于随机期望运行次数很少,跑得飞快。

您也可以像出题人那样写二分 ST 表,思路都很简单。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n , a[N * 3] , b[N * 3] , belong[N * 3] , f[N];
int L , C , s[N * 3] , t[N * 3] , maxx[N * 3];
void init() {
    C = 0;
    L = sqrt(3 * n);
    for(int i = 1; i <= n * 3; i += L) {
        s[++ C] = i;
        t[C] = min(n * 3 , i + L - 1);
        for(int j = s[C]; j <= t[C]; j ++) {
            belong[j] = C;
            maxx[C] = max(maxx[C] , a[j]);
        }
    }
}
int query_l(int x , int k) {
    int edge = belong[x];
    for(int i = x - 1; i >= s[edge]; i --) 
        if(a[i] >= k) 
            return x - i;
    for(int i = edge - 1; i >= 1; i --) 
        if(maxx[i] >= k) 
            for(int j = t[i]; j >= s[i]; j --) 
                if(a[j] >= k) 
                    return x - j;
    return -1;
}
int query_r(int x , int k) {
    int edge = belong[x];
    for(int i = x + 1; i <= t[edge]; i ++) 
        if(a[i] >= k) 
            return i - x;
    for(int i = edge + 1; i <= C; i ++) 
        if(maxx[i] >= k) 
            for(int j = s[i]; j <= t[i]; j ++) 
                if(a[j] >= k) 
                    return j - x;
    return -1;
}
int main() {
    scanf("%d" , &n);
    for(int i = 1; i <= n; i ++) 
        scanf("%d" , &a[i]) , a[i + n] = a[i] , a[i + n + n] = a[i];
    for(int i = 1; i <= n; i ++)
        scanf("%d" , &b[i]);
    init();
    for(int i = 1; i <= n; i ++) {
        f[i] = min(query_l(n + i , b[i]) , query_r(n + i , b[i]));
        if(f[i] == n) 
            f[i] = -1;
    }
    for(int i = 1; i <= n; i ++) 
        printf("%d " , f[i]);
    return 0;
}
posted @   Terac  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示