Histogram Sequence Gym - 102059J

Posted mile-star

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Histogram Sequence Gym - 102059J相关的知识,希望对你有一定的参考价值。

题目传送门:[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

 

以上是关于Histogram Sequence Gym - 102059J的主要内容,如果未能解决你的问题,请参考以下文章

Gym 240084E - Correct Bracket Sequence Editor - [线段树]

Meaningless Sequence Gym - 102832D

HDU6395-Sequence 矩阵快速幂+除法分块

R语言直方图(histogram)绘制实战

Grafana 多值浮点 histogram_quantile

histogram是啥意思