Codeforces Round #361 (Div. 2) D - Friends and Subsequences

题目大意:给你两个长度为n的数组a, b,问你有多少个问你有多少个区间满足

a中最大值等于b中最小值。

思路:我本来的想法是用单调栈求出每个点的管辖区间,然后问题就变成了巨麻烦的线段覆盖问题,就爆炸写了

一晚上假算法。正解就是枚举一个端点,然后二分找右端点的区间,因为满足一个很神奇的单调性,然后st表维护

一下区间最值就好了。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>

using namespace std;

const int N = 2e5 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 420047;

int n, a[N], b[N], bin[20], Log[N], mx[20][N], mn[20][N];

void calRmq() {
    bin[0] = 1; Log[0] = -1;
    for(int i = 1; i < 20; i++) bin[i] = bin[i - 1] * 2;
    for(int i = 1; i < N; i++)  Log[i] = Log[i / 2] + 1;

    for(int i = 1; i <= n; i++) mx[0][i] = a[i];
    for(int i = 1; i <= n; i++) mn[0][i] = b[i];

    for(int i = 1; i <= Log[n]; i++) {
        for(int j = 1; j <= n; j++) {
            if(j + bin[i] - 1 <= n) {
                mn[i][j] = min(mn[i - 1][j], mn[i - 1][j + bin[i - 1]]);
                mx[i][j] = max(mx[i - 1][j], mx[i - 1][j + bin[i - 1]]);
            }
        }
    }
}

int getVal(int x, int y, int op) {
    int t = Log[y - x + 1];
    if(op) return max(mx[t][x], mx[t][y - bin[t] + 1]);
    return min(mn[t][x], mn[t][y - bin[t] + 1]);
}

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

    calRmq();

    LL ans = 0;
    for(int i = 1; i <= n; i++) {
        int l = i, r = n, mid, ret1 = -1, ret2 = -1;
        while(l <= r) {
            mid = l + r >> 1;
            int valMin = getVal(i, mid, 0);
            int valMx = getVal(i, mid, 1);
            if(valMin > valMx) l = mid + 1;
            else if(valMin < valMx) r = mid - 1;
            else ret1 = mid, r = mid - 1;
        }

        l = i, r = n;
        while(l <= r) {
            mid = l + r >> 1;
            int valMin = getVal(i, mid, 0);
            int valMx = getVal(i, mid, 1);
            if(valMin > valMx) l = mid + 1;
            else if(valMin < valMx) r = mid - 1;
            else ret2 = mid, l = mid + 1;
        }

        if(ret1 != -1) {
            ans += ret2 - ret1 + 1;
        }
    }

    printf("%lld\n", ans);
    return 0;
}

/*
*/
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>

using namespace std;

const int N = 1e5;
const int M = 1e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int mm[N];
struct ST
{
    int dp[N][20],ty;
    void build(int n,int b[],int _ty)
    {
        ty=_ty;
        for(int i=1;i<=n;i++)
            dp[i][0]=ty*b[i];
        for(int j=1;j<=mm[n];j++)
            for(int i=1;i+(1<<j)-1<=n;i++)
                dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    int query(int x,int y)
    {
        int k=mm[y-x+1];
        return ty*max(dp[x][k],dp[y-(1<<k)+1][k]);
    }
}rmq;

int a[N];
int main() {

    for(int i=-(mm[0]=-1);i<N;i++)
        mm[i]=mm[i-1]+((i&(i-1))==0);

    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    rmq.build(n, a, 1);

    while(1) {
        int x, y; scanf("%d%d", &x, &y);
        cout << rmq.query(x, y) << endl;
    }
    return 0;
}

还有一个很神奇的st表

原文地址:https://www.cnblogs.com/CJLHY/p/9233358.html

时间: 2024-10-20 05:45:53

Codeforces Round #361 (Div. 2) D - Friends and Subsequences的相关文章

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 Round#361(div 2)

A题题目意思很简单,问一种拨号的方式(拨号手势)是不是能拨出唯一的号码(例如253就不是唯一的,因为586也是可以的) 记录电话上每个格子上下左右是否还有格子,一个拨号手势是唯一的当且仅当,所拨号码的所有格子在同一个方向不同时有格子相邻. 那么直接mark,判断一下即可: #include <cstdio> using namespace std; char s[10000]; int n,U,D,L,R; int main(){ scanf("%d %s",&n,

Codeforces Round #361 (Div. 2) C D

C 给出一个m 此时有 四个数 分别为x k*x k*k*x k*k*k*x k大于1 x大于等于1 要求求出来一个最小的值n 使其满足 这四个数中的最大值小于n 这四个数可能的组数为m 可以看出这四个数递增 所以最大值必定是第四个 所以我们二分n 需要注意的是longlong可以定义到1e18 初始应当是l小于等于可能的最小值(0) r大于等于可能的最大值(1e18) 如果初始范围就定义错误的话 二分不会出现正确答案 在这里由于控制l=mid+1或者r=mid-1 这一类的时候 容易丢失mid

Codeforces Round #361 (Div. 2) D

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

【CF】Codeforces Round #361 (Div. 2)

难得有想法写一整套题解 首先想说的是,这场CF,我感觉是div2极为不错的一场(对于中档选手<因为我就出了三题,还掉了一个-- 说笑了,感觉这一场很耐人寻味.就是那种抓破头皮想不出,知道做法后细细品味,有种   哦~~~~~这样啊~~~~好神奇!!! 的感觉 首先..秀一下战绩 不多说了 都在题里 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ A. Mike and Cellphone time limit per test 1 second memory limit per test 256 megaby

Codeforces Round #361 (Div. 2) E. Mike and Geometry Problem

题目链接:传送门 题目大意:给你n个区间,求任意k个区间交所包含点的数目之和. 题目思路:将n个区间都离散化掉,然后对于一个覆盖的区间,如果覆盖数cnt>=k,则数目应该加上 区间长度*(cnt与k的组合数) ans=ans+(len*C(cnt,k))%mod; #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorith

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i