codeforce 689D 【二分+RMQ】

本文介绍了一种利用RMQ解决区间查询问题的方法,并通过一个具体的编程实例详细展示了如何使用RMQ快速找到符合条件的区间最大值和最小值,进而解决特定问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

给出长度都为n(1<=n<=2e5)的两数组a[i]与b[i],求有多少组l与r使

比如a = {1,2,3,2,1,4},b={6,7,1,2,3,2} 有两组l与r符合条件:1.l=4,r=4,max=min=2;2.l=4,r=5,max=min=2。


题解:

我们可以思考当l固定时,可以通过求解r的范围[left,righ]得到(right-left)组符合条件的l与r,这个r的范围求解可以通过二分来求解, 判断在某个范围[l,r]是否符合条件可以通过RMQ在O(1)时间内处理,具体思路如下:

当r在范围[left,right]中可能存在符合条件的值时判断mid(mid=(left+right)/2)是否符合条件,若在[l,mid]范围,Max>Min则说明符合条件的r在[eftl,mid-1]中,Max<Min则说明符合条件的r在[mid+1,right]中,当Max==Min时符合条件的r最小值在[left,mid-1]符合条件的r的最大值在[mid+1,right]中。

这样就可以在O(2*log(n))求解某个固定值l下符合条件的r的范围,再枚举l就可以得到答案,总的时间复杂度为O(n*2*log(n))


#include<iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include<stdlib.h>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<time.h>
using namespace std;
#define MAX_N 200005
#define inf 0x7fffffff
#define LL long long
#define ull unsigned long long
#define mod 1000000007
LL INF=9e18;

int a[MAX_N];
int b[MAX_N];
int minsum[MAX_N][20];
int maxsum[MAX_N][20];
void init_RMQ(int n)
{
    for(int i=1;i<=n;i++)
        maxsum[i][0] = a[i], minsum[i][0] = b[i];
    int k = log2(1.0*n);
    for(int j=1;j<=k;j++) {
        for(int i=1;i<=n;i++) {
            if(i+(1<<j)-1<=n) {
                maxsum[i][j] = max(maxsum[i][j-1], maxsum[i+(1<<(j-1))][j-1]);
                minsum[i][j] = min(minsum[i][j-1], minsum[i+(1<<(j-1))][j-1]);
            }
        }
    }
}
int getMax(int i,int j)
{
    int k = (int)log2(1.0*(j-i+1));
    return max(maxsum[i][k], maxsum[j-(1<<k)+1][k]);
}
int getMin(int i,int j)
{
    int k = (int)log2(1.0*(j-i+1));
    return min(minsum[i][k], minsum[j-(1<<k)+1][k]);
}
int main()
{
    int n;
    cin >> n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    init_RMQ(n);
    LL ans = 0;
    //固定left,二分right
    for(int i=1;i<=n;i++) {
        //如果a[i]比b[i]则跳过,因为接下来Max只会更大Min只会更小
        if(a[i] > b[i])
            continue;
        int low = i;
        int up = n;
        int l = 0;
        int r = 0;
        while(low <= up) {
            int mid = (low + up) / 2;
            int Max = getMax(i, mid);
            int Min = getMin(i, mid);
            if(Max > Min)
                up = mid - 1;
            else if(Max < Min)
                low = mid + 1;
            else//假如mid符合条件则right最小值向low靠拢
                l = mid, up = mid - 1;

        }
        if(l) {//假如存在符合条件的最小值则搜索最大值
            up = n;
            low = l;
            while(low <= up) {
                int mid = (low + up) / 2;
                int Max = getMax(i, mid);
                int Min = getMin(i, mid);
                if(Max > Min)
                    up = mid - 1;
                else if(Max < Min)
                    low = mid + 1;
                else//假如mid符合条件则right最大值向up靠拢
                    r = mid, low = mid + 1;
            }
        }
        //printf("%d %d %d\n",i,l,r);
        if(l && r) {
            ans = ans + (LL)(r - l) + 1;
        }
    }
    cout << ans << endl;
}


### Codeforces 题目难度分布及评级标准 Codeforces 的题目难度范围广泛,涵盖了从新手到专家级别的各种挑战[^1]。该平台通过细致的分层机制来区分不同难度等级的问题,使得每位参赛者都能找到适合自己水平的任务。 #### 评分体系概述 Codeforces 使用基于积分制的评价系统,其中每道题都有一个对应的分数(rating),用于表示其相对难易程度。较低的 rating 表明这是一道较为简单的题目;而较高的 rating 则意味着更高的复杂性和解决难度。通常情况下: - **简单题**:Rating 小于等于 1200 分 - **中等偏难题**:Rating 范围大约在 1600 至 2000 分之间 - **困难题**:Rating 大于等于 2400 分 这些数值并不是固定的界限,而是根据社区反馈以及比赛实际情况调整的结果。 #### Divisions 和 Contest Types 为了更好地适应不同程度的学习者和技术爱好者的需求,Codeforces 提供了多种类型的竞赛活动,比如 Division 1, Division 2, Division 3 及 Division 4 等不同类型的比赛[^2]。每个 division 对应着不同的最低准入门槛——即参与者应该具备的基础能力或经验水平。例如,在更高级别的比赛中会遇到更多高难度的问题。 #### 技术领域覆盖 平台上发布的题目不仅限于单一的技术方向,还涉及到多个计算机科学的重要分支,如贪心算法、动态规划、图论等领域。这种多样性有助于全面锻炼编程技巧并促进跨学科思维的发展。 ```python # 示例 Python 代码片段展示如何获取某场比赛的信息 import requests def get_contest_info(contest_id): url = f"https://codeforces.com/api/contest.standings?contestId={contest_id}&from=1&count=1" response = requests.get(url).json() if 'result' not in response or 'problems' not in response['result']: return None problems = response['result']['problems'] for problem in problems: print(f"{problem['index']}: {problem['name']} - Rating: {problem.get('rating', 'N/A')}") get_contest_info(1669) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值