Friends and Subsequences

这篇博客探讨了如何解决一个编程问题,其中涉及到两个对手Mike和!Mike各自拥有一组整数序列。对于一系列查询范围(l, r),机器人计算他们对最大值和最小值回答一致的次数。通过优化算法,使用二分查找来确定相同最大最小值的区间,从而高效地计算匹配对数。" 51155755,5073303,LR逻辑回归深入解析,"['机器学习', '分类器', '预测模型', '优化算法', '数学模型']

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

Mike and !Mike are old childhood rivals, they are opposite in everything they do, except programming. Today they have a problem they cannot solve on their own, but together (with you) — who knows?

Every one of them has an integer sequences a and b of length n. Being given a query of the form of pair of integers (l, r), Mike can instantly tell the value of while !Mike can instantly tell the value of .

Now suppose a robot (you!) asks them all possible different queries of pairs of integers (l, r) (1 ≤ l ≤ r ≤ n) (so he will make exactly n(n + 1) / 2 queries) and counts how many times their answers coincide, thus for how many pairs is satisfied.

How many occasions will the robot count?

Input
The first line contains only integer n (1 ≤ n ≤ 200 000).

The second line contains n integer numbers a1, a2, …, an ( - 109 ≤ ai ≤ 109) — the sequence a.

The third line contains n integer numbers b1, b2, …, bn ( - 109 ≤ bi ≤ 109) — the sequence b.

Output
Print the only integer number — the number of occasions the robot will count, thus for how many pairs is satisfied.

Examples
input
6
1 2 3 2 1 4
6 7 1 2 3 2
output
2
input
3
3 3 3
1 1 1
output
0
Note
The occasions in the first sample case are:

1.l = 4,r = 4 since max{2} = min{2}.

2.l = 4,r = 5 since max{2, 1} = min{2, 3}.

There are no occasions in the second sample case since Mike will answer 3 to any query pair, but !Mike will always answer 1.

本题是暴力+优化
首先想到左端点找到之后枚举右边端点
然后想到对有任何一个左端点,向右的最大或者最小值是单调的

因此开始二分

二分出的区间是同样的最大最小值

因此分两次二分
一次枚举左一次枚举右

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
long long  f[200001][30], tua[200001], fx[200001][30], tub[200001], ty[200001];
long long  n, m;
void rmq(long long c)
{
    long long cc = 20;
    for (long long a = 1; a <= cc; a++)
    {
        for (long long b = 1; b <= c; b++)
        {
            if (b + (1 << a) - 1 <= c)
            {
                f[b][a] = max(f[b][a - 1], f[b + (1 << (a - 1))][a - 1]);
                fx[b][a] = min(fx[b][a - 1], fx[b + (1 << (a - 1))][a - 1]);
            }
        }
    }
}
long long xunwenda(long long zuo, long long you)
{
    long long k = log2(you - zuo + 1);
    return max(f[zuo][k], f[you - (1 << k) + 1][k]);
}
long long xunwenxiao(long long zuo, long long you)
{
    long long k = log2(you - zuo + 1);
    return min(fx[zuo][k], fx[you - (1 << k) + 1][k]);
}
long long jc(long long z, long long y)
{
    if (xunwenda(z, y) > xunwenxiao(z, y))return 0;
    else if (xunwenda(z, y) == xunwenxiao(z, y))return 1;
    return 2;
}
int main()
{
#define int long long
    int n;
    cin >> n;
    for (int a = 1; a <= n; a++)scanf("%lld", &tua[a]);
    for (int a = 1; a <= n; a++)scanf("%lld", &tub[a]);
    for (int a = 1; a <= n; a++)f[a][0] = tua[a];
    for (int a = 1; a <= n; a++)fx[a][0] = tub[a];
    rmq(n);
    int qw = 0;
    for (int a = 1; a <= n; a++)
    {
        int z = a, y = n;
        int tt = 0;
        while (z <= y)
        {
            int mid = (z + y) / 2;
            int qq = jc(a, mid);
            if (qq == 1)
            {
                tt = max(tt, mid);
            }
            if (qq == 0)
            {
                y = mid - 1;
            }
            else
            {
                z = mid + 1;
            }
        }
        ty[a] += tt;
    }
    for (int a = 1; a <= n; a++)
    {
        int z = a, y = n;
        int tt = 2100000;
        while (z <= y)
        {
            int mid = (z + y) / 2;
            int qq = jc(a, mid);
            if (qq == 1)
            {
                tt = min(tt, mid);
            }
            if (qq == 0 || qq == 1)
            {
                y = mid - 1;
            }
            else if (qq == 2)
            {
                z = mid + 1;
            }
        }
        ty[a] -= tt;
    }
    for (int a = 1; a <= n; a++)
    {
        if (ty[a] < 0)continue;
        qw += ty[a]+1;
    }
    cout << qw;
}
### 关于回文子序列的算法及其示例 #### 定义与概念 回文是指正读和反读都相同的字符序列。对于给定字符串中的任意字符组合形成的子序列,如果该子序列满足上述条件,则称为回文子序列。 #### 动态规划求解最长回文子序列 为了找到一个字符串中最长的回文子序列,可以采用动态规划的方法来解决这个问题。设 `dp[i][j]` 表示从第 i 到 j 的子串内的最长回文子序列长度: - 当 s[i]==s[j] 时, dp[i][j]=dp[i+1][j−1]+2; - 否则, dp[i][j]=max(dp[i+1][j],dp[i][j−1]). 最终的结果保存在 `dp[0][len(s)-1]` 中[^3]. ```python def longest_palindromic_subseq(s: str) -> int: n = len(s) # 创建二维数组用于存储中间结果 dp = [[0]*n for _ in range(n)] # 初始化单个字符的情况 for i in range(n): dp[i][i] = 1 # 填充表格 for length in range(2, n + 1): for start in range(n - length + 1): end = start + length - 1 if s[start] == s[end]: dp[start][end] = dp[start+1][end-1] + 2 else: dp[start][end] = max(dp[start+1][end], dp[start][end-1]) return dp[0][-1] ``` 此方法的时间复杂度为 O(n²),空间复杂度同样为 O(n²). #### 枚举所有可能的回文子序列 除了寻找最长的回文子序列外,还可以通过枚举的方式找出所有的不同回文子序列。这种方法适用于较短的输入字符串,并且可以通过位掩码技术实现高效的遍历。 ```python from collections import defaultdict def count_distinct_palindrome_subsequences(text: str) -> list[str]: results = set() memo = {} def backtrack(start=0, path=""): nonlocal text, results, memo key = (start, path) if key not in memo: temp_set = {path} if path == path[::-1] else {} for index in range(start, len(text)): new_path = path + text[index] if new_path == new_path[::-1]: temp_set.add(new_path) temp_set |= backtrack(index + 1, new_path) memo[key] = temp_set results.update(memo[(start, path)]) return memo[(start, path)] backtrack() return sorted(list(results)) ``` 这段代码会返回按字典序排列的不同回文子序列列表.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值