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);
            }
        }
    }
  • 相关阅读:
    07: mysql锁和事物隔离
    06: mysql索引查找原理及调优
    06: 字典、顺序表、列表、hash树 实现原理
    05:树结构
    02:MongoDB操作
    01:MongoDB基础
    02: CMDB设计思路
    二级制包安装Tomcat 与 RPM包安装Tomcat
    Docker的volume机制实现容器数据的持久性存储
    配置docker的私有仓库
  • 原文地址:https://www.cnblogs.com/Saurus/p/7374853.html
Copyright © 2011-2022 走看看