CF1156E Special Segments of Permutation(单调栈)

题目

给定一个长度为 n n n的排列 p p p,求有多少区间 [ l , r ] [l,r] [l,r]满足, p [ l ] + p [ r ] = m a x p [ i ] p[l]+p[r]=max{p[i]} p[l]+p[r]=maxp[i],其中 l < = i < = r l<=i<=r l<=i<=r

题解

  • 预处理出左边第一个大于 i i i的数和右边第一个大于 i i i的数(单调栈维护一下即可)
  • 左端点显然只能在 ( L , i ) (L,i) (L,i),右端点只能在 ( i , R ) (i,R) (i,R),枚举长度较小的区间判断是否可行即可

code

#include <bits/stdc++.h>

using namespace std; 

const int N = 2e5 + 100; 

int n, top; 
int a[N], s[N], L[N], R[N], pos[N]; 

int main() {
	scanf("%d", &n); 
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]); 
		pos[a[i]] = i; 
	}
	s[top = 0] = 0; 
	for (int i = 1; i <= n; ++i) {
		while (top && a[i] > a[s[top]]) top--; 
		L[i] = s[top], s[++top] = i; 
	}
	s[top = 0] = n + 1; 
	for (int i = n; i >= 1; --i) {
		while (top && a[i] > a[s[top]]) top--; 
		R[i] = s[top], s[++top] = i; 
	}
	int ans = 0; 
	for (int i = 1; i <= n; ++i) {
		if (i - L[i] < R[i] - i) {
			int Max = a[i]; 
			for (int j = L[i] + 1; j < i; ++j) {
				int tmp = a[j]; 
				if (pos[Max - tmp] > i && pos[Max - tmp] < R[i]) ++ans; 
			}
		}
		else {
			int Max = a[i]; 
			for (int j = i + 1; j < R[i]; ++j) {
				int tmp = a[j]; 
				if (pos[Max - tmp] > L[i] && pos[Max - tmp] < i) ++ ans; 
			}
		}
	}
	printf("%d\n", ans);
	return 0; 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值