【CF739C】Alyona and towers

Cs063ndL.jpg (1920×1200)
CF739CAlyona and towers
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Alyona has built n towers by putting small cubes some on the top of others. Each cube has size 1 × 1 × 1. A tower is a non-zero amount of cubes standing on the top of each other. The towers are next to each other, forming a row.
Sometimes Alyona chooses some segment towers, and put on the top of each tower several cubes. Formally, Alyona chooses some segment of towers from li to ri and adds di cubes on the top of them.
Let the sequence a1, a2, ..., an be the heights of the towers from left to right. Let's call as a segment of towers al, al + 1, ..., ar a hill if the following condition holds: there is integer k (l ≤ k ≤ r) such that al < al + 1 < al + 2 < ... < ak > ak + 1 > ak + 2 > ... > ar.
After each addition of di cubes on the top of the towers from li to ri, Alyona wants to know the maximum width among all hills. The width of a hill is the number of towers in it.
Input
The first line contain single integer n (1 ≤ n ≤ 3·105) — the number of towers.
The second line contain n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — the number of cubes in each tower.
The third line contain single integer m (1 ≤ m ≤ 3·105) — the number of additions.
The next m lines contain 3 integers each. The i-th of these lines contains integers liri and di (1 ≤ l ≤ r ≤ n1 ≤ di ≤ 109), that mean that Alyona puts di cubes on the tio of each of the towers from li to ri.
Output
Print m lines. In i-th line print the maximum width of the hills after the i-th addition.
Example
input
Copy
5
5 5 5 5 5
3
1 3 2
2 2 1
4 4 1
output
Copy
2
4
5
Note
The first sample is as follows:
After addition of 2 cubes on the top of each towers from the first to the third, the number of cubes in the towers become equal to [7, 7, 7, 5, 5]. The hill with maximum width is [7, 5], thus the maximum width is 2.
After addition of 1 cube on the second tower, the number of cubes in the towers become equal to [7, 8, 7, 5, 5]. The hill with maximum width is now [7, 8, 7, 5], thus the maximum width is 4.
After addition of 1 cube on the fourth tower, the number of cubes in the towers become equal to [7, 8, 7, 6, 5]. The hill with maximum width is now [7, 8, 7, 6, 5], thus the maximum width is 5.

题意翻译
现在有n个数,m个操作,每次区间加一个数,对于每一次操作,你要找出最长al...ar ,满足
k[l,r],al<al+1<al+2<...<ak>ak+1>ak+2>...>ar
输出其长度。
输入:
第一行一个整数n,表示数的个数。
第二行n个整数ai
第三行一个整数m,表示操作个数。
下面m行,每行3个整数, li,ri,di,表示将liri的数字加di
输出:
对于每个操作,输出操作完后的答案(见题意)
样例解释:
  1. 5 5 5 5 5  7 7 7 5 5 ,最长的是7 5,长度为2
  2. 7 7 7 5 5  7 8 7 5 5 ,最长的是7 8 7 5 ,长度为4
  3. 7 8 7 5 5  7 8 7 6 5 ,最长的是7 8 7 6 5 ,长度为5
题目较为恶心,线段树的 push_up 很难写
主要是分类讨论比较多,一类一类讨论即可

inline void push_up(const Tp &rt, const Tp &l, const Tp &r)
    {
        Tp mid = (l + r) >> 1;

        tr[rt].L = tr[ls].L;
        tr[rt].R = tr[rs].R;
        tr[rt].v = std::max(tr[ls].vtr[rs].v);

        // update suf
        tr[rt].suf = tr[ls].suf;
        if (tr[ls].suf == mid - l + 1 && tr[rs].L < tr[ls].R)
        {
            tr[rt].suf += tr[rs].suf;
        }

        // update pre
        tr[rt].pre = tr[rs].pre;
        if (tr[rs].pre == r - mid && tr[ls].R < tr[rs].L)
        {
            tr[rt].pre += tr[ls].pre;
        }

        // update pre_hill && suf_hill
        tr[rt].suf_hill = tr[ls].suf_hill;
        tr[rt].pre_hill = tr[rs].pre_hill;

        if (tr[ls].pre == mid - l + 1 && tr[ls].R < tr[rs].L)
        {
            tr[rt].suf_hill = std::max(tr[rt].suf_hilltr[ls].pre + tr[rs].suf_hill);
        }

        if (tr[ls].pre_hill == mid - l + 1 && tr[ls].R > tr[rs].L)
        {
            tr[rt].suf_hill = std::max(tr[rt].suf_hilltr[ls].suf_hill + tr[rs].suf);
        }

        if (tr[rs].suf == r - mid && tr[rs].L < tr[ls].R)
        {
            tr[rt].pre_hill = std::max(tr[rt].pre_hilltr[rs].suf + tr[ls].pre_hill);
        }

        if (tr[rs].suf_hill == r - mid && tr[rs].L > tr[ls].R)
        {
            tr[rt].pre_hill = std::max(tr[rt].pre_hilltr[ls].pre + tr[rs].suf_hill);
        }

        // update v
        tr[rt].v = std::max({tr[rt].vtr[rt].suf_hilltr[rt].pre_hilltr[rt].suftr[rt].pre});

        if (tr[ls].R > tr[rs].L)
        {
            tr[rt].v = std::max(tr[rt].vtr[ls].pre_hill + tr[rs].suf);
        }

        if (tr[ls].R < tr[rs].L)
        {
            tr[rt].v = std::max(tr[rt].vtr[rs].suf_hill + tr[ls].pre);
        }
    }
其实官方的题解已经写得很好了
uDFSBJlz.jpg (1092×367)
照着实现即可
整个代码见下
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")

#include "bits/stdc++.h"

#define mem(x) memset((x), 0sizeof((x)))
#define il __attribute__((always_inline))

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#if __cplusplus > 201403L
#define r
#else
#define r register
#endif

#define c const

namespace _c
{
double pi = acos(-1.0);
namespace min
{
int i8 = -128;
int i16 = -32768;
int i = -2147483647 - 1;
c ll l = -9223372036854775807LL - 1;
} // namespace min

namespace max
{
int i8 = 127;
int i16 = 32767;
int i = 2147483647;
c ll l = 9223372036854775807LL;
} // namespace max
} // namespace _c

namespace _f
{
template <typename T>
inline c T gcd(T m, T n)
{
    while (n != 0)
    {
        T t = m % n;
        m = n;
        n = t;
    }
    return m;
}

template <typename T>
inline c T abs(c T &a)
{
    return a > 0 ? a : -a;
}

template <typename T>
inline T pow(T a, T b)
{
    T res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = res * a;
        }
        a = a * a;
        b >>= 1;
    }
    return res;
}

template <typename T>
inline T pow(T a, T b, c T &m)
{
    a %= m;
    T res = 1;
    while (b > 0)
    {
        if (b & 1)
        {
            res = res * a % m;
        }
        a = a * a % m;
        b >>= 1;
    }
    return res % m;
}
} // namespace _f

namespace io
{
template <typename T>
inline T read()
{
    r T res = 0, neg = 1;
    char g = getchar();
    for (; !isdigit(g); g = getchar())
    {
        if (g == '-')
        {
            neg = -1;
        }
    }
    for (; isdigit(g); g = getchar())
    {
        res = res * 10 + g - '0';
    }
    return res * neg;
}
template <typename T>
inline void read(T &t)
{
    t = read<T>();
}
template <typename T>
inline void readln(c T first, c T last)
{
    for (r T it = first; it != last; it++)
    {
        read(*it);
    }
}

template <typename T>
inline void _write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9)
    {
        _write(x / 10);
    }
    putchar(x % 10 + '0');
}
template <typename T>
inline void write(c T &x, c char &sep = ' ')
{
    _write(x);
    putchar(sep);
}
template <typename T>
inline void writeln(c T &x)
{
    write(x, '\n');
}
template <typename T>
inline void writeln(c T first, c T last, c char &sep = ' 'c char &ends = '\n')
{
    for (r T it = first; it != last; it++)
    {
        write(*it, sep);
    }
    putchar(ends);
}

#if __cplusplus >= 201103L
template <typename Ttypename... Args>
void read(T &x, Args &... args)
{
    read(x);
    read(args...);
}
#endif
} // namespace io
#undef c
#undef r

const int N = 3e5 + 5;

int n, m;
int a[N];

template <typename Tp>
struct SegTree
{
    struct T
    {
        Tp v;

        Tp L, R;

        Tp pre, suf;
        Tp pre_hill, suf_hill;

        Tp tag;

        inline void set_to(const Tp &x)
        {
            v = L = R = pre = suf = pre_hill = suf_hill = 1;
            L = R = x;
        }
    } tr[N * 4];

#define lson(x) ((x) << 1)
#define rson(x) ((x) << 1 | 1)
#define ls lson(rt)
#define rs rson(rt)

    inline void push_up(const Tp &rt, const Tp &l, const Tp &r)
    {
        Tp mid = (l + r) >> 1;

        tr[rt].L = tr[ls].L;
        tr[rt].R = tr[rs].R;
        tr[rt].v = std::max(tr[ls].vtr[rs].v);

        // update suf
        tr[rt].suf = tr[ls].suf;
        if (tr[ls].suf == mid - l + 1 && tr[rs].L < tr[ls].R)
        {
            tr[rt].suf += tr[rs].suf;
        }

        // update pre
        tr[rt].pre = tr[rs].pre;
        if (tr[rs].pre == r - mid && tr[ls].R < tr[rs].L)
        {
            tr[rt].pre += tr[ls].pre;
        }

        // update pre_hill && suf_hill
        tr[rt].suf_hill = tr[ls].suf_hill;
        tr[rt].pre_hill = tr[rs].pre_hill;

        if (tr[ls].pre == mid - l + 1 && tr[ls].R < tr[rs].L)
        {
            tr[rt].suf_hill = std::max(tr[rt].suf_hilltr[ls].pre + tr[rs].suf_hill);
        }

        if (tr[ls].pre_hill == mid - l + 1 && tr[ls].R > tr[rs].L)
        {
            tr[rt].suf_hill = std::max(tr[rt].suf_hilltr[ls].suf_hill + tr[rs].suf);
        }

        if (tr[rs].suf == r - mid && tr[rs].L < tr[ls].R)
        {
            tr[rt].pre_hill = std::max(tr[rt].pre_hilltr[rs].suf + tr[ls].pre_hill);
        }

        if (tr[rs].suf_hill == r - mid && tr[rs].L > tr[ls].R)
        {
            tr[rt].pre_hill = std::max(tr[rt].pre_hilltr[ls].pre + tr[rs].suf_hill);
        }

        // update v
        tr[rt].v = std::max({tr[rt].vtr[rt].suf_hilltr[rt].pre_hilltr[rt].suftr[rt].pre});

        if (tr[ls].R > tr[rs].L)
        {
            tr[rt].v = std::max(tr[rt].vtr[ls].pre_hill + tr[rs].suf);
        }

        if (tr[ls].R < tr[rs].L)
        {
            tr[rt].v = std::max(tr[rt].vtr[rs].suf_hill + tr[ls].pre);
        }
    }

    inline void build(const Tp &rt, const Tp &l, const Tp &r)
    {
        if (l == r)
        {
            tr[rt].set_to(a[l]);
            return;
        }

        Tp mid = (l + r) >> 1;

        build(ls, l, mid);
        build(rs, mid + 1, r);

        push_up(rt, l, r);
    }

    inline void push_down(const Tp &rt)
    {
        tr[ls].tag += tr[rt].tag;
        tr[rs].tag += tr[rt].tag;

        tr[ls].R += tr[rt].tag;
        tr[ls].L += tr[rt].tag;
        tr[rs].R += tr[rt].tag;
        tr[rs].L += tr[rt].tag;

        tr[rt].tag = 0;
    }

    inline void update(const Tp &rt, const Tp &l, const Tp &r, const Tp &ul, const Tp &ur, const Tp &k)
    {
        if (ul <= l && r <= ur)
        {
            tr[rt].tag += k;
            tr[rt].L += k;
            tr[rt].R += k;
            return;
        }

        push_down(rt);
        Tp mid = (l + r) >> 1;

        if (ul <= mid)
        {
            update(ls, l, mid, ul, ur, k);
        }

        if (ur > mid)
        {
            update(rs, mid + 1, r, ul, ur, k);
        }

        push_up(rt, l, r);
    }

#undef ls
#undef rs
#undef lson
#undef rson
};

SegTree<ll> Seg;

int main()
{
    io::read(n);
    io::readln(a + 1, a + n + 1);

    Seg.build(11, n);

    io::read(m);

    for (int i = 1, l, r, k; i <= m; i++)
    {
        io::read(l, r, k);
        Seg.update(11, n, l, r, k);
        io::writeln(Seg.tr[1].v);
    }
}


评论

此博客中的热门博文

高中地理必修一知识点总结

【CF961F】k-substrings

偷税与漏税的区别