ICPC 2020
ICPC 2020

E. Landscape Generator

Interactive Creative Players Collective (ICPC) is working on a new computer game for which they want to generate realistic landscapes. One of the ICPC engineers proposed an algorithm inspired by geological processes. The algorithm starts with a flat landsca...

Updated May 21, 2026
Track ICPC
Year 2020
Statement Text + PDF
TeXC++Statement textStatement PDF

Problem Statement

Formatted from the contest statement text, with sample tests broken out into copyable blocks.

Time limit 4 seconds

Interactive Creative Players Collective (ICPC) is working on a new computer game for which they want to generate realistic landscapes. One of the ICPC engineers proposed an algorithm inspired by geological processes. The algorithm starts with a flat landscape and repeatedly modifies it by lifting or lowering continuous blocks, thus forming horsts (lifted blocks) and grabens (lowered blocks). The blocks to be lifted or lowered are selected at random. ICPC hopes to obtain realistic landscapes this way. Your task is to interpret any sequence of such modifications and output the resulting landscape. The landscape is represented by a sequence of n integer height values, one for each integer point from 1 to n on the x-axis. Figure E.1 illustrates an example by connecting the height values with line segments.

2
       1   2   3   4   5   6   7   8   9 10 11 12 13 14 15 16 17 18 19 20
 −2
 −4
 −6
 −8
−10
Figure E.1: Illustration of the landscape generated by Sample Input 1.

Initially the height is 0 at all n points. This flat shape is subjected to a sequence of modifications. Each modification applies one of the following four operations with two integer parameters x1 ≤ x2 :

R: Raise – increase the height by 1 at all points between x1 and x2 inclusive. D: Depress – decrease the height by 1 at all points between x1 and x2 inclusive. H: Hill – add a new linearly shaped hill between x1 and x2 . V: Valley – add a new linearly shaped valley between x1 and x2 .

Adding a hill to the current landscape works as follows. The heights at points x1 and x2 are increased by 1. If x2 − x1 > 1, the heights at points x1 + 1 and x2 − 1 are increased by 2. If x2 − x1 > 3, the heights at points x1 + 2 and x2 − 2 are increased by 3, and so on. Figure E.2 shows an example. Adding a valley works in the same way except the heights are decreased instead. The maximal change of height happens in the middle between x1 and x2 . If x2 − x1 is odd, there will be two neighboring points with maximal change, otherwise just one.

Input

The first line of input contains two integers n and k, where n (1 ≤ n ≤ 200 000) is the number of points, and k (0 ≤ k ≤ 200 000) is the number of modifications. The n points along the x-axis are numbered from 1 to n. The next k lines describe the modifications. Each line contains one character c and two integers x1 and x2 , where c (one of R, D, H or V) designates the operation and x1 and x2 (1 ≤ x1 ≤ x2 ≤ n) specify its parameters.

3
2
1
1        2        3        4       5        6        7
Figure E.2: Illustration of the landscape generated by Sample Input 2.

Output

Output n lines, where the ith line contains the height at point i after applying all modifications in the given order.

Sample Tests

Sample 1
Sample Input
 20 13
 H 12 13
 D 5 18
 R 13 14
 R 8 16
 H 2 3
 V 10 19
 V 3 13
 R 8 13
 V 3 10
 D 5 18
 V 11 12
 R 1 6
 R 14 19
Sample Output
1
2
0
-3
-7
-9
-11
-9
-7
-6
-6
-5
-3
-4
-5
-4
-4
-3
0
0
Sample 2
Sample Input
 7 1
 H 1 6
Sample Output
1
2
3
3
2
1
0

Editorial

The solution write-up is rendered from the LaTeX source, with equations kept live through MathJax.

Key Observations

  • Every operation is purely additive, so the order does not matter. We only need the sum of all contributions at each position.

  • A constant raise/depress on $[x_1, x_2]$ is just the linear function \[ 0 \cdot x + (\pm 1) \] on that interval.

  • A hill or valley is piecewise linear. Let \[ m = \left\lfloor \frac{x_1 + x_2}{2} \right\rfloor. \] Then a hill on $[x_1, x_2]$ equals \[ x - x_1 + 1 \quad \text{for } x \in [x_1, m], \] and \[ x_2 - x + 1 \quad \text{for } x \in [m+1, x_2]. \] A valley is just the negative of the same profile.

  • So every operation can be decomposed into at most two interval updates of a linear function \[ a x + b. \]

  • If we keep two difference arrays, one for the active coefficient $a$ and one for the active coefficient $b$, then after a prefix sum we know the total linear function applying at each position.

Algorithm

  1. Maintain two difference arrays:

    • diffA for slope coefficients,

    • diffB for constant coefficients.

    • An update ``add $ax+b$ on $[L,R]$'' is handled by \[ \texttt{diffA}[L] += a,\quad \texttt{diffA}[R+1] -= a, \] and similarly for diffB.

    • For R and D, add the constant functions $+1$ or $-1$ on $[x_1,x_2]$.

    • For H or V, let sign be $+1$ for a hill and $-1$ for a valley, and let $m=\lfloor (x_1+x_2)/2 \rfloor$. Then add \[ \texttt{sign} \cdot x + \texttt{sign}(1-x_1) \] on $[x_1,m]$, and \[ -\texttt{sign} \cdot x + \texttt{sign}(x_2+1) \] on $[m+1,x_2]$.

    • After processing all operations, sweep from left to right. Prefix-sum diffA and diffB into the current coefficients $A$ and $B$. The final height at position $i$ is then \[ A \cdot i + B. \] enumerate

      Correctness Proof

      We prove that the algorithm returns the correct answer.

      Lemma 1.

      For any interval $[L,R]$, the update ``add $ax+b$ for every $x \in [L,R]$'' is represented correctly by adding $a$ and $b$ to the two difference arrays at $L$ and subtracting them at $R+1$.

      Proof.

      After taking prefix sums of the difference arrays, coefficient $a$ is present exactly on indices in $[L,R]$, and absent elsewhere. The same is true for coefficient $b$. Therefore the value contributed at index $x$ is exactly $ax+b$ when $x \in [L,R]$ and $0$ otherwise. □

      Lemma 2.

      Let $m=\lfloor (x_1+x_2)/2 \rfloor$. A hill on $[x_1,x_2]$ is exactly the sum of the two linear pieces \[ x-x_1+1 \quad \text{on } [x_1,m] \] and \[ x_2-x+1 \quad \text{on } [m+1,x_2]. \] A valley is the negative of the same decomposition.

      Proof.

      For $x \in [x_1,m]$, the distance from $x$ to the nearer endpoint is $x-x_1$, so the hill adds $x-x_1+1$. For $x \in [m+1,x_2]$, the nearer endpoint is the right one, so the hill adds $x_2-x+1$. These are exactly the values specified in the statement: $1$ at both ends, increasing by $1$ toward the middle, with one peak for odd length and two equal middle values for even length. Negating the profile gives a valley. □

      Lemma 3.

      For every position $i$, the algorithm computes exactly the total contribution of all operations at $i$.

      Proof.

      By Lemma 2, each input operation is decomposed into one or two linear interval updates that reproduce its exact effect. By Lemma 1, each such linear interval update is represented exactly in the difference arrays. Summing all active coefficients at position $i$ therefore gives the sum of all operation contributions at $i$, which is the final height there. □

      Theorem.

      The algorithm outputs the correct answer for every valid input.

      Proof.

      Every input operation is transformed into an equivalent set of linear interval updates by Lemma 2. Those updates are accumulated exactly by the two difference arrays by Lemma 1. By Lemma 3, the final sweep computes the exact total height at every position. Therefore the algorithm outputs the correct landscape. □

      Complexity Analysis

      Each modification performs only $O(1)$ work, and the final sweep is linear. So the total running time is $O(n+k)$.

      The two difference arrays use $O(n)$ memory.

      Implementation Notes

      • The split point is always $m=\lfloor (x_1+x_2)/2 \rfloor$. This handles both odd and even interval lengths correctly.

      • Using 64-bit integers is important because many large hills or valleys can accumulate.

      • The second linear segment is empty when $x_1=x_2$; the helper simply skips empty intervals.

Code

C++ solution used for this page.

C++

Clean code view with a raw-file link when you want the original source.

Raw file
#include <bits/stdc++.h>
using namespace std;

namespace {

void add_linear(vector<long long>& diff_a,
                vector<long long>& diff_b,
                int left,
                int right,
                long long a,
                long long b) {
    if (left > right) {
        return;
    }
    diff_a[left] += a;
    diff_a[right + 1] -= a;
    diff_b[left] += b;
    diff_b[right + 1] -= b;
}

void solve() {
    int n, k;
    cin >> n >> k;

    vector<long long> diff_a(n + 2, 0);
    vector<long long> diff_b(n + 2, 0);

    for (int q = 0; q < k; ++q) {
        char type;
        int x1, x2;
        cin >> type >> x1 >> x2;

        if (type == 'R') {
            add_linear(diff_a, diff_b, x1, x2, 0, 1);
        } else if (type == 'D') {
            add_linear(diff_a, diff_b, x1, x2, 0, -1);
        } else {
            long long sign = (type == 'H' ? 1 : -1);
            int mid = (x1 + x2) / 2;

            add_linear(diff_a, diff_b, x1, mid, sign, sign * (1LL - x1));
            add_linear(diff_a, diff_b, mid + 1, x2, -sign, sign * (x2 + 1LL));
        }
    }

    long long current_a = 0;
    long long current_b = 0;
    for (int i = 1; i <= n; ++i) {
        current_a += diff_a[i];
        current_b += diff_b[i];
        cout << current_a * i + current_b << '\n';
    }
}

}  // namespace

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    solve();
    return 0;
}

Source Files and Assets

Raw files are still available here when you want the original TeX, C++, or statement assets.

Show raw files