• 单调队列+二分 G


    B. Queue

    这个题目会做的很偶然,突然想到的,因为我们要求离这只海象的最远的比他年轻的海象,这个年轻的海象可以用单调栈维护。

    就是从前往后遍历一遍,单调栈里面存年龄从小往大的海象,这个为什么这么存呢,因为如果后面有比这个队列里面更年轻的海象,

    那么就可以更新,而且这个更新是正确的,不会有影响,这个可以自己想一想/

    然后就可以得到一个单调栈的数组,这个时候因为单调栈是单调的,所以可以用二分来查找我们所需要的值。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 1e5 + 10;
    typedef long long ll;
    int queue_min[maxn];
    int f1 = 1, t1 = 1, r = 1;
    int ans[maxn];
    ll num[maxn];
    ll a[maxn];
    
    int ok(ll s)
    {
        int x = 1, y = t1;
        int mid = (x + y) / 2;
        while(x<=y)
        {
            mid = (x + y) / 2;
            if (a[queue_min[mid]] >= s) y = mid-1;
            else x = mid + 1;
            //printf("x=%d y=%d mid=%d
    ",x,y, mid);
        }
        //printf("mid=%d queue_min=%d
    ", mid, queue_min[mid]);
        if (a[queue_min[mid]] >= s) return queue_min[mid - 1];
        return queue_min[mid];
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
        f1 = 1, t1 = 1, r = 1;
        for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
        queue_min[1] = 1;
        while(r<n)
        {
            r++;
            while (f1 <= t1 && a[r] < a[queue_min[t1]]) t1--;
            queue_min[++t1] = r;
        }
        for (int i = f1; i <= t1; i++) {
            num[i] = a[queue_min[i]];
            // printf("queue_min[%d]=%d
    ", i, queue_min[i]);
            // printf("num[%d]=%lld
    ", i, num[i]);
        }
        for(int i=1;i<=n;i++)
        {
            int f = ok(a[i]);
            //printf("F=%d
    ",f);
            if (f < i) ans[i] = -1;
            else ans[i] = f - i - 1;
            printf("%d ", ans[i]);
        }
        printf("
    ");
        return 0;
    }
    单调栈 海象

    小阳买水果

    这个题目和上面那个其实是一样的,但是我居然没有发现,这个要先前缀和处理一下,然后你就发现其实求的就是 比如 i ,求的就是 i 后面的比 i 更大的sum的最远位置。

    也是二分+单调队列

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e6 + 10;
    typedef long long ll;
    int queue_max[maxn];
    int a[maxn], num[maxn];
    ll sum[maxn];
    int f1, t1;
    int r;
    
    int ok(ll s) {
        int x = 1, y = t1;
        int mid = (x + y) / 2;
        while (x <= y) {
            mid = (x + y) / 2;
            if (sum[queue_max[mid]] > s) x = mid + 1;
            else y = mid - 1;
            //printf("x=%d y=%d mid=%d
    ", x, y, mid);
        }
        //printf("mid=%d queue_min=%d
    ", mid, queue_min[mid]);
        if (sum[queue_max[mid]] <= s) return queue_max[mid - 1];
        return queue_max[mid];
    }
    
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &sum[i]);
            sum[i] += sum[i - 1];
        //    printf("sum[%d]=%lld
    ", i, sum[i]);
        }
        f1 = 1, t1 = 1;
        r = 2;
        queue_max[1] = 1;
        int ans = 0;
        while (r <= n) {
            while (t1 >= f1 && sum[r] > sum[queue_max[t1]]) t1--;
            queue_max[++t1] = r;
            //printf("queue_max[%d]=%d
    ", t1, queue_max[t1]);
            r++;
        }
        for (int i = f1; i <= t1; i++) {
            num[i] = sum[queue_max[i]];
            //printf("queue[%d]=%d
    ", i, queue_max[i]);
        }
        for (int i = 1; i <= n; i++) {
            int f = ok(sum[i]);
            //printf("i=%d f=%d
    ", i, f);
            if (f > i)
            {
                if (sum[i] >= 0) ans = max(ans, f - i + 1);
                else ans = max(ans, f - i);
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    二分+单调队列
  • 相关阅读:
    id4的数据库持久化写法
    docker 加速镜像的地址收集
    mongodb 的ID转换实体要注意的地方
    net core3.0 常用封装状态码总结
    JAVA8—————StringJoiner类
    BigDecimal加减乘除
    mysql 查询奇偶数
    Java遍历Map对象的方式
    Java中List, Integer[], int[]的相互转换
    springboot 读取resources下的文件然后下载
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11195563.html
Copyright © 2020-2023  润新知