码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1175F 尺取法 性质分析

时间:2019-06-06 22:53:02      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:std   最大值   位置   print   printf   一个   包含   分析   ==   

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

思路(大佬代码):我们发现,一个排列一定含有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 尺取法 性质分析

标签:std   最大值   位置   print   printf   一个   包含   分析   ==   

原文地址:https://www.cnblogs.com/pkgunboat/p/10987079.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!