LG11243

为了方便思考,以下分析满足条件 \(i<j\)。对于 \(i>j,a_i<a_j\) 的情况,则转化为 \(i<j,a_i>a_j\)(前后对调)。

先分析 \(i<j,a_i<a_j\) 的情况。显然,必须要满足 \(a_i \le a_{i + 1} \le a_{i + 2} \le \cdots \le a_j\) 时,才有可能产生贡献,否则一定可以构造反例。除此之外,为了保证 \(a_i < a_j\),必须至少存在一个 \(k \in [i,j)\) 使 \(a_k < a_{k+1}\),这样才能产生贡献。\(i<j,a_i>a_j\) 的情况同理。于是不难写出 \(O(n^2)\) 的做法:

#include <iostream>
#include <cstdio>

using namespace std;

int n,c[1000001],ans,flag;
string s;

int main()
{
	int T;
	cin >> T;
	while( T -- )
	{
		cin >> n;
		cin >> s;
		ans = 0;
		for( int i = 1 ; i < n ; i ++ )
		{
			if( s[i - 1] == '>' ) c[i] = 1;
			if( s[i - 1] == '=' ) c[i] = 2;
			if( s[i - 1] == '<' ) c[i] = 3;
		}
		for( int i = 1 ; i <= n ; i ++ )
		{
			flag = 0;
			for( int j = i ; j < n ; j ++ )
			{
				if( c[j] == 1 ) break;
				if( c[j] == 3 ) flag = 1;
				if( flag ) ans ++;
			}
			flag = 0;
			for( int j = i ; j < n ; j ++ )
			{
				if( c[j] == 3 ) break;
				if( c[j] == 1 ) flag = 1;
				if( flag ) ans ++;
			}
		}
		cout << ans << '\n';
	} 
	return 0;
}

考虑优化该算法。还是以 \(i<j,a_i<a_j\) 的情况为例,固定 \(i\) 后,第一个产生贡献的位置应该是第一个 \(k\) 使 \(a_{k-1} < a_k\),最后一个产生贡献的位置应该是第一个 \(l\) 使 \(a_l > a_{l+1}\)(之后的一定都不合法)。根据上文的分析,在 \([k,l]\) 上都能产生贡献。因此预处理每个位置后的第一个大于号和小于号的位置,再一遍计算贡献即可。

时间复杂度 \(O(n)\)

#include <iostream>
#include <cstdio>
#define int long long

using namespace std;

int n,c[1000001],f1[1000001],f2[1000001],ans,flag1,flag2,pd1,pd2;
string s;

signed main()
{
	int T;
	cin >> T;
	while( T -- )
	{
		cin >> n;
		cin >> s;
		ans = 0;
		for( int i = 1 ; i < n ; i ++ )
		{
			if( s[i - 1] == '>' ) c[i] = 1;
			if( s[i - 1] == '<' ) c[i] = 2;
			if( s[i - 1] == '=' ) c[i] = 3;
			f1[i] = f2[i] = 0; 
		}
		f1[n] = f2[n] = 0;
		for( int i = n - 1 ; i >= 1 ; i -- )
		{
			f1[i] = f1[i + 1];
			f2[i] = f2[i + 1];
			if( c[i] == 1 )
				f1[i] = i;
			if( c[i] == 2 )
				f2[i] = i;
		}
		for( int i = 1 ; i < n ; i ++ )
		{
			if( f1[i] )
			{
				if( !f2[i] )
					ans += n - f1[i];
				else if( f2[i] > f1[i] )
					ans += f2[i] - f1[i];
			}
			if( f2[i] )
			{
				if( !f1[i] )
					ans += n - f2[i];
				else if( f1[i] > f2[i] )
					ans += f1[i] - f2[i];
			}
		}
		cout << ans << '\n';
	} 
	return 0;
}
posted @ 2025-09-08 18:36  FormulaOne  阅读(9)  评论(0)    收藏  举报