zoukankan      html  css  js  c++  java
  • Histogram Sequence Gym

    题目传送门:[https://codeforces.com/gym/102059/problem/J](https://codeforces.com/gym/102059/problem/J)

    题意: 给定一个直方图,一个长度为n的序列表示每个柱子的高度,有一个数组A记录着直方图中每个不同子矩形的面积,A数组是按从小到大排序好的,给你L和R,让你输出A[L]到A[R]。
    思路:单调栈+二分+优先队列
    首先用单调栈求出每个柱子往左右扩展的范围,然后二分A[L]处储存的面积大小,因为知道每个柱子的扩展范围后,可以计算有多少个不同子矩形的面积为相同的值,因此二分查找A[L],通过计算有多少不同个子矩形的面积小于等于该答案,来检查答案是否合法,找到一个面积值S, 使得小于等于S的子矩形个数大于等于L;记录下这个面积,然后通过将每个该面积大小的子矩形长度加一得到的面积存入优先队列,面积小的在前,从队首取出,检查该面积的子矩形是否存在,若存在,计算存在的数量,计入答案,直到数目到达R;
    对于如何计算小于等于一个面积值的子矩形个数,有如下公式:

    //
    // Created by mile on 2019/7/29.
    //
    //gym 102059j
    //二分+单调栈+优先队列
    
    #include <bits/stdc++.h>
    
    #define ps push
    #define pb push_back
    #define mp make_pair
    using namespace std;
    const int maxn = 300005;
    typedef long long ll;
    
    struct Node {
        ll id, h, w;
        Node() {}
        Node(ll a, ll b, ll c) : id(a), h(b), w(c) {}
        bool operator < (const Node& a) const {
            return h*w > a.h*a.w;
        }
    };
    
    struct Histogram {
        ll n, L, R, sumlen, h[maxn], l[maxn], r[maxn], st[maxn];
    
        ll init(int n) {
            this->n = n;
            sumlen = 0;
            for(int i = 1; i <= n; i++) scanf("%I64d", &h[i]), sumlen += h[i], l[i] = 1, r[i] = n;
            scanf("%I64d%I64d", &L, &R);
            int tail = 0;
            for(int i = 1; i <= n+1; i++) {
                while (tail >= 1 && h[st[tail]] > h[i]) {
                    r[st[tail]] = i-1;
                    l[i] = l[st[tail]];
                    tail--;
                }
                if(tail) l[i] = st[tail]+1;
                st[++tail] = i;
            }
        }
    
        ll getnum(ll x, ll y) {
            x = max(1ll, y-x+1);
            return (y+x)%2 == 0 ? (y+x)/2*(y-x+1) : (y-x+1)/2*(y+x);
        }
    
        ll getlen(ll x, ll y, ll z, ll len) {
            return max(0ll, z-y-len+2)-max(0ll, z-x-len+1)-max(0ll, x-y-len+1);
        }
    
        ll solve(ll x) {
            ll sum = 0;
            for(int i = 1; i <= n; i++) {
                if(h[i] > x) continue;
                ll len = r[i]-l[i]+1;
                sum += getnum(x/h[i], len)-getnum(x/h[i], r[i]-i)-getnum(x/h[i], i-l[i]);
            }
            return sum;
        }
    
        ll binary_search(ll L, ll& ans) {
            ll lr = 1, rr = sumlen;
            while(lr < rr) {
                long long mid = (lr+rr)>>1;
                long long val = solve(mid);
                if(val < L) {
                    lr = mid+1;
                } else {
                    rr = mid;
                }
            }
            ans = lr;
            return solve(lr);
        }
    
        void work() {
            ll ans = 0;
            ll tmp = binary_search(L, ans);
            while(L <= R && L <= tmp) {
                printf("%I64d ", ans);
                L++;
            }
            priority_queue<Node> Q;
            for(int i = 1; i <= n; i++) Q.ps(Node(i, h[i], ans/h[i]+1));
            Node nxt;
            while(L <= R) {
                nxt = Q.top();
                Q.pop();
    =            if(nxt.id >= 300005 || nxt.id <= 0) break;
                ll tlen = getlen(nxt.id, l[nxt.id], r[nxt.id], nxt.w);
                if(!tlen) continue;
                while(tlen > 0 && L <= R) {
                    printf("%I64d ", nxt.h*nxt.w);
                    tlen--;
                    L++;
                }
                ++nxt.w;
                Q.ps(nxt);
            }
        }
    };
    Histogram ac;
    
    int main()
    {
        ll n;
        scanf("%I64d", &n);
        ac.init(n);
        ac.work();
        return 0;
    }
    View Code
  • 相关阅读:
    Retrofit 传递json 和 复杂参数类型List<T>
    Android Activity has leaked window that was originally added
    Android 集成GoogleMap,实现定位和获取位置信息
    Android 新浪微博开放平台应用 android签名怎么获得
    Android java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader......couldn't find "libweibosdkcore.so
    Android 微信第三方登录
    Android RxVolley = Volley + RxJava + OkHttp
    Android 微博sdk接入授权指南
    Android之通过配置Flavor实现一个项目打包成多个apk
    Android第三方登陆之新浪微博Weibo篇(原生登陆授权)
  • 原文地址:https://www.cnblogs.com/mile-star/p/11267226.html
Copyright © 2011-2022 走看看