CodeForces 689D Friends and Subsequences

枚举,二分,$RMQ$。

对于一个序列来说,如果固定区间左端点,随着右端点的增大,最大值肯定是非递减的,最小值肯定是非递增的。

因此,根据这种单调性,我们可以枚举区间左端点$L$,二分找到第一个位置${{p_1}}$,使得$\mathop {\max }\limits_{i = L}^{{p_1}} {a_i} = \mathop {\min }\limits_{i = L}^{{p_1}} {b_i}$;再次二分找到最后一个位置${{p_2}}$,使得$\mathop {\max }\limits_{i = L}^{{p_2}} {a_i} = \mathop {\min }\limits_{i = L}^{{p_2}} {b_i}$。那么以$L$为左端点的区间,有${{p_2}}-{{p_1}}+1$个。查询区间最值的话可以倍增预处理一下。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-6;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0; while(!isdigit(c)) c = getchar();
    while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); }
}

const int maxn=200010;
int a[maxn],b[maxn],n;
int MAX[maxn][30],MIN[maxn][30];

void RMQ_init()
{
    for(int i=0;i<n;i++) MAX[i][0]=a[i],MIN[i][0]=b[i];
    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++)
            MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<(j-1))][j-1]),
            MIN[i][j]=min(MIN[i][j-1],MIN[i+(1<<(j-1))][j-1]);
}

int RMQ_MAX(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;
    return max(MAX[L][k],MAX[R-(1<<k)+1][k]);
}

int RMQ_MIN(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;
    return min(MIN[L][k],MIN[R-(1<<k)+1][k]);
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int i=0;i<n;i++) scanf("%d",&b[i]);
    RMQ_init();

    LL ans=0;
    for(int i=0;i<n;i++)
    {
        if(b[i]<a[i]) continue;
        int p1=-1,p2=-1;
        int L=i,R=n-1;
        while(L<=R)
        {
            int mid=(L+R)/2;
            int mx=RMQ_MAX(i,mid),mn=RMQ_MIN(i,mid);
            if(mx>mn) R=mid-1;
            else if(mx==mn) R=mid-1,p1=mid;
            else L=mid+1;
        }

        L=i,R=n-1;
        while(L<=R)
        {
            int mid=(L+R)/2;
            int mx=RMQ_MAX(i,mid),mn=RMQ_MIN(i,mid);
            if(mx>mn) R=mid-1;
            else if(mx==mn) L=mid+1,p2=mid;
            else L=mid+1;
        }

        if(p1==-1) continue;
        ans=ans+(LL)(p2-p1+1);
    }
    printf("%lld\n",ans);

    return 0;
}
时间: 2024-07-29 00:27:07

CodeForces 689D Friends and Subsequences的相关文章

CF 689D - Friends and Subsequences

689D - Friends and Subsequences 题意: 大致跟之前题目一样,用ST表维护a[]区间max,b[]区间min,找出多少对(l,r)使得maxa(l,r) == minb(l,r) 切题的感觉很爽唉 同样而二分查找,找最小和最大下标满足条件 cf中%I64d, 一般是%lld 代码: #include<bits/stdc++.h> #define ll long long const int maxn=200010; int sta[maxn][18]; int s

CodeForces - 844C Sorting by Subsequences (排序+思维)

You are given a sequence a1,?a2,?...,?an consisting of different integers. It is required to split this sequence into the maximum number of subsequences such that after sorting integers in each of them in increasing order, the total sequence also wil

Codeforces Round #361 div2

ProblemA(Codeforces Round 689A): 题意: 给一个手势, 问这个手势是否是唯一. 思路: 暴力, 模拟将这个手势上下左右移动一次看是否还在键盘上即可. 代码: 1 #include <cmath> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <ctime> 6 #include <set> 7 #incl

codeforces 497E Subsequences Return

codeforces 497E Subsequences Return 想法 做完这题,学了一些东西. 1.求一个串不同子序列个数的两种方法.解一 解二 2.这道题 \(n\) 很大,很容易想到矩阵加速,但是之前遇到的矩阵的题目,矩阵都是相同的,这题的矩阵虽然不同,但是至多 \(k\) 个,并且出现规律与 \(0\) ~ \(n-1\) 的 \(k\) 进制形态有关.题解中基于这点进行的优化和 \(dp\) 的思想又很像. 代码 #include<bits/stdc++.h> using na

Codeforces 597C. Subsequences (树状数组+dp)

题目链接:http://codeforces.com/contest/597/problem/C 给你n和数(1~n各不同),问你长为k+1的上升自序列有多少. dp[i][j] 表示末尾数字为i 长度为j的上升子序列个数,但是dp数组是在树状数组的update函数中进行更新. update(i, val, j)函数表示在i的位置加上val,更新dp[i][j]. sum(i, j)就是求出末尾数字小于等于i 且长度为j的子序列有多少个. 1 //#pragma comment(linker,

Codeforces Round #361 (Div. 2) D. Friends and Subsequences RMQ+二分

题目链接 http://codeforces.com/problemset/problem/689/D 代码 1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 6 const int maxn = 200000 + 10; 7 int n, a[maxn], b[maxn]; 8 int d_min[maxn][30]; 9 int d_max[m

Codeforces Round #361 (Div. 2) D.Friends and Subsequences (multiset + 尺取法)

D. Friends and Subsequences 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

codeforces 597C C. Subsequences(dp+树状数组)

题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output For the given sequence with n different elements find the number of increasing subsequences with k + 1 elements. It is

Codeforces 1132G Greedy Subsequences 线段树

Greedy Subsequences 我们先找到每个点的右边第一个比它大的, 然后从大的往它建边, 然后可以发现这是一棵树. 我们令d[ i ] 为 i 号点往上走最多能走几步, 我们能用线段树维护d 的值. 我们加入点 i 的时候, 我们把它的值设为 d[ fa ] + 1, 我们删除 i 的时候, 把 i 这棵子树中的d 都减 1, 每次询问最大值就好啦. #include<bits/stdc++.h> #define LL long long #define LD long doubl