【2019.10.15】网课 Za

stack S
A[0] = +OO  S.push(0)
for (i = 1 ~ N)
{
    while (A[S.top()] < A[i])
        S.pop()
    L[i] = S.top()
    S.push(i)
}
deque Q
for (i = 1 ~ N)
{
    while (Q.empty() == false && A[Q.back()] > A[i])
        Q.pop_back()
    Q.push_back(i)
    if (Q.front() < i - K + 1)
        Q.pop_front()
    if (i >= K)
        min[i - K + 1, i] = A[Q.front()]
}
O(N)
deque Q
for (i = 1 ~ N)
{
    while (Q.empty() == false && A[Q.back()] > A[i])
        Q.pop_back()
    Q.push_back(i)
    if (Q.front() < i - K + 1)
        Q.pop_front()
    if (i >= K)
        min[i - K + 1, i] = A[Q.front()]
}
O(N)

P3143

sort(A)
for (r = 1 ~ N)
{
    while (A[r] - A[l] > K)
        ++l
    Pre[r] = max(Pre[r - 1], r - l + 1)
}
for (l = N ~ 1)
{
    while (A[r] - A[l] > K)
        --r
    Suf[l] = max(Suf[l + 1], r - l + 1)
}
for (i = 1 ~ N)
    Ans max= Pre[i - 1] + Suf[i]

P

P1102

P2671

二分

1083借教室

1314 聪明的质检员

关押罪犯也可以二分

2680

1613

1081

归并排序

int A[N], T[N];
long long int solve(int l, int r)
{
    if (l == r)
        return 0LL;
    int m = l + ((r - l) >> 1);
    LL Ret = solve(l, m) + solve(m + 1, r);
    for (int i = m + 1, j = 1, k = l - 1;i <= r;++i)
    {
        while (j <= m && A[j] <= A[i])
            T[++k] = A[j++];
        Ret += m - j + 1; 
        T[++k] = A[i];
    }
    for (int i = l;i <= r;++i)
        A[i] = T[i];
    return Ret;
}

单调栈

可以线性寻找一个元素左边(或右边)第一个满足某种条件的元素

比较常见的问题是:给定一个序列,对于每个数寻找其左边或 右边)第一个比它大(或比它小)的数

以寻找每个数左边第一个比它大的数为例
从右往左扫,维护一个栈,存储当前还没找到比它大的数的元素
可以发现栈中的元素有两个信息是单调的:下标和数值
下标单调是因为入栈顺序的原因
数值单调是因为,如果不单调的话会推出矛盾
那么每次可以让栈中一些元素找到比它大的元素,把它们从栈中删除。可以发现这些元素一定是栈顶的一部分。这么一番操作后, 数据结构的性质没有发生变化
每个元素被至多加入一次和删除一次,所以时间复杂度是线性的

two-pointer双指针法

大概是我之前搞过的尺取法?于是复习了一遍

• 双指针就是有两个指针a和b。这个方法目的一般是为了统计这样 的二元组的一些信息(比如数量、极值等)

• 这样的二元组可能描述了一些其他东西,比如说一个闭合区间

• 如果分析题目性质可以发现,一个指针向一个方向动,另一个指 针也只会单向移动,也就是所谓的“单调性”,那就可以用这个方 法,移动指针的时间复杂度也是线性的

你可能感兴趣的:(【2019.10.15】网课 Za)