Codeforces 1175F 尺取法 性质分析

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1175F 尺取法 性质分析相关的知识,希望对你有一定的参考价值。

题意:给你一个数组,问有多少个区间,满足区间中的数构成一个排列。

思路(大佬代码):我们发现,一个排列一定含有1,所以我们不妨从1开始入手计算构成排列的区间个数。对于每个扫描到的1(假设处于位置i),我们向左右分别延伸,直到遇到1或者到了数组边界,延伸的时候,需要处理下左边到i的最大值和右边到i的最大值。处理之后,我们先处理排列的最大值在左端的情况。我们暴力枚举每一个位置,把它作为区间的左端点(L),现在我们去确认右端点(R),首先,右端点必须大于等于i,因为要包含1。我们先让右端点向左移,因为右端点的mx值不能大于等于左端点的,不然相当于mx值出现了两次。并且R - L + 1必须小于等于mx[L],因为mx[L]是当前排列的最大值,也是排列的长度。之后,因为R - L + 1可能小于mx[L],我们需要增大R,直到长度满足要求,或者下一个数已经在L到R之间出现过了。此时,如果长度满足要求,那么就找到了一个符合要求的排列,答案+1。最大值在右端同理。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 300010;
int in_LR[maxn];//in_LR == tot :在L,R之间 
int a[maxn], mx[maxn];
int main() 
	int n, tot = 0, L, R, ans = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) 
		scanf("%d", &a[i]);
	
	for (int i = 1; i <= n; i++) 
		if(a[i] != 1) continue;
		mx[i] = 1;
		for (int j = i - 1; a[j] != 1 && j >= 1; j--)
			mx[j] = max(mx[j + 1], a[j]);
		for (int j = i + 1; j <= n && a[j] != 1; j++)
			mx[j] = max(mx[j - 1], a[j]);
		//处理最大值在左半边的情况
		tot++;
		L = i, R = i;
		while(in_LR[a[L]] != tot && L >= 1) 
			in_LR[a[L]] = tot;//放入R和L之间 
			L--;
		
		for (L++; L <= i; in_LR[a[L++]] = tot - 1) 
			while(R > i && (R - L + 1 > mx[L] || mx[R] >= mx[L])) 
				in_LR[a[R--]] = tot - 1;
			while(R < n && R - L + 1 < mx[L]) 
				if(in_LR[a[R + 1]] == tot || a[R + 1] >= mx[L]) break;
				in_LR[a[++R]] = tot;
			
			if(R - L + 1 == mx[L]) ans++;
		
		//处理最大值在右半边的情况
		tot++;
		L = i, R = i;
		while(in_LR[a[R]] != tot && R <= n) 
			in_LR[a[R]] = tot;//放入R和L之间 
			R++;
		
		for (R--; R > i; in_LR[a[R--]] = tot - 1) 
			while(L < i && (R - L + 1 > mx[R] || mx[L] >= mx[R])) 
				in_LR[a[L++]] = tot - 1;
			while(L > 1 && R - L + 1 < mx[R]) 
				if(in_LR[a[L - 1]] == tot || a[L - 1] >= mx[R]) break;
				in_LR[a[--L]] = tot;
			
			if(R - L + 1 == mx[R]) ans++;
		
	
	printf("%d\n", ans);

  

以上是关于Codeforces 1175F 尺取法 性质分析的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces - 958 F2 Lightsabers (medium) . (尺取法)

尺取法 C - Vasya and String CodeForces - 676C

尺取法

#333 Div2 Problem B Approximating a Constant Range(尺取法)

POJ - 2566 Bound Found(尺取法+前缀和)

尺取法简介