【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。这个方法目的一般是为了统计这样 的二元组的一些信息(比如数量、极值等)

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

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

posted @ 2019-10-16 11:35  委屈的咸鱼鱼鱼鱼  阅读(211)  评论(2编辑  收藏  举报