1. 程式人生 > >luogu P1318 積水面積

luogu P1318 積水面積

這道題有點繞,其實想明白很簡單,想不明白你就會像我一樣很早很早之前就看過這題,完全不會,看過很多次,完全沒思路,今天又突然想起這道題,然而還是不會。。。
直到睡覺前突然間有了靈感三分鐘打完程式碼,過了樣例交上結果A了;
題目描述

一組正整數,分別表示由正方體迭起的柱子的高度。若某高度值為x,表示由x個正立方的方塊迭起(如下圖,0<=x<=5000)。找出所有可能積水的地方(圖中藍色部分),統計它們可能積水的面積總和(計算的是圖中的橫截面積。一個立方體的位置,為一個單位面積)。

如圖:柱子高度變化為 0 1 0 2 1 2 0 0 2 0


圖中藍色部分為積水面積,共有6個單位面積積水。

輸入輸出格式

輸入格式:
兩行,第一行n,表示有n個數(3<=n<=10000)。第2行連續n個數表示依次由正方體迭起的高度,保證首尾為0。

輸出格式:
一個數,可能積水的面積。

輸入輸出樣例

輸入樣例#1: 複製
10
0 1 0 2 1 2 0 0 2 0
輸出樣例#1: 複製
6

每一個點能不能有積水在於在同一高度它的左右是不是都有柱子,即左右都有比該點高的柱子,則該處可以有積水,可以積水的地方為左邊最大值和右邊最大值的最小值與該點的差值,就正著求出每個點之前出現過的最大值(柱子最高值),反著再求一遍每個點之後的最大值(柱子最高值),再迴圈一遍求出差值求和即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
    int x = 0; int f = 1; char c = getchar();
    while(c<'0'||c>'9'){
        if(c == '-')f = -f;
        c = getchar();
    }
    while(c<='9'&&c>='0'){
        x = x * 10 + c - '0';
        c = getchar(); 
    }
    return x*f;
} 
int l,r,n,ans;
int maxx[5000000],minn[5000000],pic[5000000];
int main(){
    n = read();
    for(int i = 1; i<=n; i++)pic[i] = read();
    for(int i = 1; i<=n; i++){
        maxx[i] = max(maxx[i - 1],pic[i]);
    }
    for(int i = n; i>=1; i--){
        minn[i] = max(minn[i+1],pic[i]);
    }
    for(int i = 1; i<=n; i++){
        ans += max(0,min(maxx[i],minn[i]) - pic[i]);
    }
    cout<<ans;
    
    return 0;
}