Submission #340195

#TimeUsernameProblemLanguageResultExecution timeMemory
340195blueFancy Fence (CEOI20_fancyfence)C++11
100 / 100
373 ms18884 KiB
#include <iostream>
#include <algorithm>
using namespace std;

/*
Sort all the rectangles by height.
Repeat:
    Look at the tallest rectangle with height H and width W.
    Let h be the larger height among its neighbors.
    Count all fancy rectangles whose top edge is in the range [h+1, H] = (W*(W+1)/2) * ((H-h)*(H-h+1)/2)
    Reduce the height of the tallest rectangle to h and merge it with the right neighbors

Reverse the above algorithm

Solution
Repeat:
    Look at the lowest rectangle with height H
    Find the rectangles to the left and right closest to this rectangle which have height strictly less than H.
        (Sparse table + Binary search)
    Let the total width bounded between (not inside either rectangle) these rectangles be W
    Add (Hchoose2 + Hchoose1) * (Wchoose2 + Wchoose1)
*/

long long N;
long long h[100002][18];
long long w[100001];
long long l2[100002];
long long rect[100001];

long long mod = 1e9 + 7;

long long hmin(long long l, long long r)
{
    return min(h[l][l2[r-l+1]], h[r - (1LL << l2[r-l+1]) + 1][l2[r-l+1]]);
}

int main()
{
    cin >> N;

    h[0][0] = h[N+1][0] = 0;
    for(long long i = 1; i <= N; i++)
    {
        cin >> h[i][0];
    }
    for(long long j = 1; j <= 17; j++)
    {
        for(long long i = 1; i + (1LL << j) - 1 <= N; i++)
        {
            h[i][j] = min(h[i][j-1], h[i + (1LL << (j-1))][j-1]);
        }
    }

    w[0] = 0;
    for(long long i = 1; i <= N; i++)
    {
        cin >> w[i];
        w[i] = (w[i] + w[i-1]) % mod;
    }

    l2[1] = 0;
    for(long long i = 2; i <= N; i++) l2[i] = l2[i/2] + 1;

    for(long long i = 0; i <= N; i++) rect[i] = i;
    sort(rect+1, rect+N+1,
        [] (long long a, long long b)
        {
            if(h[a][0] == h[b][0]) return a < b;
            return h[a][0] < h[b][0];
        }
    );
    //for(int i = 1; i <= N; i++) cout << rect[i] << ' ';
    //cout << '\n';

    long long res = 0;

    long long curr, L, R;
    long long x, y, m;
    for(long long i = 1; i <= N; i++)
    {
        curr = rect[i];
        if(h[curr][0] == h[rect[i-1]][0] && hmin(rect[i-1], curr) == h[curr][0]) continue;
    //    cout << curr << ' ' << h[curr][0] << ' ';

        x = 0;
        y = curr-1;
        while(x != y)
        {
            m = (x+y)/2 + 1;
            if(hmin(m, curr-1) >= h[curr][0]) y = m-1;
            else x = m;
        }
        L = x;
                                //Problem is, with nodes of equal heights
        x = curr+1;
        y = N+1;
        while(x != y)
        {
            m = (x+y)/2;
            if(hmin(curr+1, m) >= h[curr][0]) x = m+1;
            else y = m;
        }
        R = y;

        long long y1 = h[curr][0];
        //long long y2 = h[rect[i-1]][0];
        long long y2 = max(h[L][0], h[R][0]);
        long long x = w[R-1] - w[L];

        res = (res + (((x*(x+1))/2)%mod) * (( mod + (((y1*(y1+1))/2)%mod)  -  (((y2*(y2+1))/2)%mod)  ) % mod)) % mod;
        //cout << res << '\n';
    }
    cout << res << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...