zoukankan      html  css  js  c++  java
  • 计蒜客16492 building(二分线段树/分块)

    题解:

    考虑用线段树维护楼的最大值,然后这个问题就很简单了。

    每次可以向左二分出比x高的第一个楼a,同理也可以向右二分出另一个楼b,如果a,b都存在,答案就是b-a-1。

    注意到二分是可以直接在线段树上进行的,所以复杂度是O(nlogn)。

    当然这里是用分块做的,更暴力一些。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    const int maxn = 1e5 + 100, maxN = 500;
    int B[maxN], Tag[maxN];
    int a[maxn];
    int n, m, N, L;
    void Update(int i){
        if(Tag[i] == -1) return;
        int bl = i*L, br = min(n, (i+1)*L-1);
        for(int j = bl; j <= br; j++) a[j] = Tag[i];
        Tag[i] = -1;
    }
    void Change(int l, int r, int v){
        for(int i = 0; i < N; i++){
            int bl = i*L, br = min(n, (i+1)*L-1);
            if(l <= bl && br <= r){
                Tag[i] = v;
                B[i] = v;
            } else if(bl <= l && l <= br && bl <= r && r <= br){
                Update(i);
                B[i] = max(B[i], v);
                for(int j = l; j <= r; j++) a[j] = v;
            } else if(bl <= l && l <= br){
                Update(i);
                B[i] = max(B[i], v);
                for(int j = l; j <= br; j++) a[j] = v;
            } else if(bl <= r && r <= br){
                Update(i);
                B[i] = max(B[i], v);
                for(int j = bl; j <= r; j++) a[j] = v;
            }
        }
    }
    
    int Findl(int x){
        int bi = x/L;
        int bl = bi*L, br = min(n, (bi+1)*L-1);
        Update(bi);
        for(int i = x-1; i >= bl; i--){
            if(a[i] > a[x]) return i;
        }
        for(int i = bi-1; i >= 0; i--){
            if(B[i] > a[x]){
                bl = i*L, br = min(n, (i+1)*L-1);
                Update(i);
                for(int j = br; j >= bl; j--)
                    if(a[j] > a[x]) return j;
            }
        }
        return -1;
    }
    
    int Findr(int x){
        int bi = x/L;
        int bl = bi*L, br = min(n, (bi+1)*L-1);
        Update(bi);
        for(int i = x+1; i <= br; i++){
            if(a[i] > a[x]) return i;
        }
        for(int i = bi+1; i < N; i++){
            if(B[i] > a[x]){
                bl = i*L, br = min(n, (i+1)*L-1);
                Update(i);
                for(int j = bl; j <= br; j++)
                    if(a[j] > a[x]) return j;
            }
        }
        return -1;
    }
    
    
    int main()
    {
        int x, y, z;
        cin>>n;
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        L = sqrt(n+0.5);
        N = n/L + 1;
        for(int i = 0; i < N; i++) Tag[i] = -1;
        for(int i = 1; i <= n; i++){
            B[i/L] = max(B[i/L], a[i]);
        }
        cin>>m;
        for(int i = 1; i <= m; i++){
            scanf("%d", &x);
            if(x == 1){
                scanf("%d %d %d", &x, &y, &z);
                Change(x, y, z);
            } else {
                scanf("%d", &x);
                int l = Findl(x), r = Findr(x);
                if(l == -1 || r == -1) printf("-1
    ");
                else printf("%d
    ", r-l-1);
            }
        }
    }
  • 相关阅读:
    Navicat for Mysql远程连接数据时报(1045错误)Access denied for user 'root'@'localhost' (using password yes);
    添加数据源,管理工具--数据源(ODBC),点击添加不显示该驱动
    安装mysql odbc遇到error 1918.errror installing ODBC driver mysql ODBC 5.3 ANSI Drive
    ISO9126软件质量模型
    敏捷测试到底是灵丹妙药还是又一个忽悠
    CSS中背景图片的background-position中的left top到底是相对于谁的?
    制作可扩展的按钮
    CSS中的HSLA颜色
    JavaScript(jQuery)中的事件委托
    从零开始写一个微前端框架-数据通信篇
  • 原文地址:https://www.cnblogs.com/Saurus/p/7374853.html
Copyright © 2011-2022 走看看