题目链接

被C题卡到了,一开始没想到,不过感觉就算不被卡,也很难出D。

A题

题意:给你n个数,问你怎么排,能使得相邻两个数\(a_i,a_{i + 1}\)满足\((a_i+a_{i + 1})/2\)是整数的数对最多

思路:显然只需要先放奇数再放偶数(反过来也行)就可。

vector<int> even, odd;
int n;
 
int main()
{
	IOS; 
	int T;
	cin >> T;
	while(T --)
	{
		odd.clear();
		even.clear();
		cin >> n;
		for(int i = 1 ; i <= n ; i ++)
		{
			int x;
			cin >> x;
			if(x & 1) odd.push_back(x);
			else even.push_back(x);
		}
		
		for(int i = 0 ; i < odd.size() ; i ++)
			cout << odd[i] << " ";
		for(int i = 0 ; i < even.size() ; i ++)
			cout << even[i] << " ";
		cout << endl;
	}
	
	return 0;
}

B题

题意:给你一个长度为\(3n\)字符串,问你能否将它拆分成n个长度为\(3\)的"TMT"子序列

思路:类似括号匹配,只需要满足M的数量始终不比T大,然后每出现一个M后面都会对应出现一个T即可。

string s;
int n;
 
int main()
{
	IOS; 
	int T;
	cin >> T;
	while(T --)
	{
		cin >> n;
		cin >> s;
		int t = 0, m = 0, cnt = 0;
		bool flag = true;
		for(int i = 0 ; i < s.size() ; i ++)
		{
			if(s[i] == 'T')
			{
				t ++;
				if(cnt) cnt --;	
			}
			else
			{
				m ++, cnt ++;
				if(m > t) flag = false;			
			}
		}
		if(t != m * 2 || cnt) flag = false;
		if(flag) cout << "YES\n";
		else cout << "NO\n";
	}
	
	return 0;
}

C题

题意:给你n个数,定义\(d_i = max(a_1, ..., a_i) - min(a_1, ..., a_i)\),问你怎么排能使得 \(\sum_{k = 1}^n d_k\)最小

思路:区间DP,f[i][j] 表示对a[i ~ j]进行处理所得的\(\sum_{k = 1}^{j - i + 1} d_k\)的最小值。
f[i][j]只能从 f[i + 1][j] 和 f[i][j - 1] 中的一个转移过来,取最优的那个转移即可。
这题需要维护最大值和最小值,因此开了结构体

struct node{
	ll maxd, mind, sum;
};
node f[N][N];	//f[i][j] 表示 a[i ~ j]中所求值的最小值 
int a[N], n;

int main()
{
	IOS; 
	{
		cin >> n;
		for(int i = 1 ; i <= n ; i ++)	cin >> a[i];
		sort(a + 1, a + n + 1);
		
		for(int i = 1 ; i <= n ; i ++)
			f[i][i] = {a[i], a[i], 0};
		
		ll maxd, mind, nowmaxd, nowmind, add1, add2;
		for(int len = 2 ; len <= n; len ++)
			for(int l = 1 ; l + len - 1 <= n ; l ++)
			{
				int r = l + len - 1;
				maxd = f[l + 1][r].maxd, mind = f[l + 1][r].mind;
				nowmaxd = max(maxd, f[l][l].maxd);
				nowmind = min(mind, f[l][l].mind);
				add1 = nowmaxd - nowmind;
				
				maxd = f[l][r - 1].maxd, mind = f[l][r - 1].mind;
				nowmaxd = max(maxd, f[r][r].maxd);
				nowmind = min(mind, f[r][r].mind);
				add2 = nowmaxd - nowmind;
				
				if(f[l + 1][r].sum + add1 < f[l][r - 1].sum + add2)
				{
					f[l][r].sum = f[l + 1][r].sum + add1;
					f[l][r].maxd = max(f[l + 1][r].maxd, f[l][l].maxd);	
					f[l][r].mind = min(f[l + 1][r].mind, f[l][l].mind);					
				}

				else
				{
					f[l][r].sum = f[l][r - 1].sum + add2;
					f[l][r].maxd = max(f[l][r - 1].maxd, f[r][r].maxd);	
					f[l][r].mind = min(f[l][r - 1].mind, f[r][r].mind);
				}			
			}

		cout << f[1][n].sum << endl;
	}
	
	return 0;
}

D题

这题我没做出来,也没时间了,后面再补。
题意:

思路:


E题

这题应该可以补,后面有机会补一下。
题意:

思路: