CF R866 div.2

A

 当一个"_ "的右边没有“^”时,答案增加,发现这对于中间的序列是充分必要的。
当位置 \(1\) 为 "_"时,我们必须在其前面加一个"^";当整个字符串为 "^"时,特判一下答案。

B

 发现给定01串当全是“1”时,我们直接输出 \(n*n\)。考虑一般的情况,我们发现将面积表示出来
\(S=a+b,a+b=x\)\(x\)为定值,即连续的“1”的最大个数。那么我们就由均值不等式可知当 \(a=b\)时,面积最大。
考虑实际,当 \(x=2*k+1\),即为奇数时,不能使 \(a=b\),那么我们让 \(a=b-1\),此时面积最大。
由于题目的性质,我们需要将首尾连成圈来确定这个 \(x\) 的值。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int T, n;
char s[N << 1];
int main(){
	cin >> T;
	while(T --){
		cin >> (s + 1);
		n = strlen(s + 1);
		bool flag = true;
		LL ans = 0;
		int maxn = 0, cnt = 0;
		for(int i = 1; i <= n; i++)
			if(s[i] == '0')
				flag = false, maxn = max(maxn, cnt), cnt = 0;
			else cnt ++;
		for(int i = 1; i <= n; i++)
			if(s[i] == '0')
				flag = false, maxn = max(maxn, cnt), cnt = 0;
			else cnt ++;
		maxn = max(cnt, maxn);
		if(flag) ans = (LL)n * n;
		else {
			if(maxn % 2 == 0) ans = (LL)maxn / 2 * (LL)(maxn / 2 + 1);
			else ans = (LL) (maxn + 1) / 2 * (maxn + 1) / 2;
		}
		cout << ans << endl;
	}
	return 0;
}

C

  首先,我们考虑这样一个问题:若使得这个改变后的序列的 \(mex\) 值比原来大 \(1\) ,需要满足什么条件。
我们进行一次操作后,设原来的 \(mex\) 值为 \(M\) 不难发现:

  • 1 要让新序列有 \(1 \sim M\) 的至少一个元素。
  • 2 要使新序列中不含有 \(M+1\) 的元素,否则新的 \(mex\) 值不可能为 \(M+1\)

那么我们同时明确了这次操作的目的,我们采取这样的方式来模拟操作。
由于第二点的必要性且我们只有一次操作,我们将序列中的所有 \(M+1\) 给赋值为 \(M\) ,若新序列不符合要求,那一定无解。
对于剩下的情况,我们还需要特判一下该序列是不是一个 \(1 \sim M-1\) 的排列(这也是不合法的)。
其他情况均合法,且此方案可行。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int T, n, a[N], A[N];
int main(){
	cin >> T;
	while(T --){
		scanf("%d", &n);
		for(int i = 1; i <= n; i++)
			scanf("%d", &a[i]), A[i] = a[i];
		sort(A + 1, A + n + 1);
		int cnt = 0;
		bool flag = true;
		for(int i = 1; i <= n; i++)
			if(A[i] == cnt) cnt ++;
			else flag = false;
		if(flag){
			puts("NO");
			continue;
		}
		int l = 0, r = n + 1;
		for(int i = 1; i <= n; i++)
			if(a[i] == cnt + 1){
				l = i;
				break;
			}
		for(int i = n; i; i--)
			if(a[i] == cnt + 1){
				r = i;
				break;
			}
		for(int i = l; i <= r; i++)
			a[i] = cnt;
		sort(a + 1, a + n + 1);
		int cntt = 0;
		for(int i = 1; i <= n; i++)
			if(a[i] == cntt) cntt ++;
		if(cnt == cntt - 1 || l == 0) puts("YES");
		else puts("NO");
	}
	return 0;
}

D

由于本题性质,所以我们可以找到最大的长和宽 \(Mn,Mm\)
并且,原矩形至多只有两种情况:(\(Mn\),\(S/Mn\)),(\(S/Mm\),\(Mm\)),\(S\)面积可以通过输入直接计算。
现在我们需判断这两种情况的合法性,我们发现可以暴力模拟判断。
\(map\) 存给定子矩形,每次可以通过 \(map\) 判断,在 \(O(nlogb)\) 的时间内完成

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int T, n;
int main(){
	cin >> T;
	while(T --){
		cin >> n;
		map<LL, multiset<LL>> mp1, mp2;
		LL maxw = 0, maxh = 0;
		LL S = 0;
		for(int i = 1; i <= n; i++){
			LL a, b;
			scanf("%lld%lld", &a, &b);
			mp1[a].insert(b);
			mp2[b].insert(a);
			maxw = max(maxw, a);
			maxh = max(maxh, b);
			S += (LL)a * b;
		}
		set<pair<LL, LL>> ans;
		auto check = [](int n, LL W, LL H, int idx, map<LL, multiset<LL>> mp1, map<LL, multiset<LL>> mp2){
			while(W > 0 && H > 0){
				LL tot = 0;
				if(idx == 0){
					for(auto it: mp1[W]){
						tot += it;
						n --;
						mp2[it].erase(mp2[it].find(W));
					}
					H -= tot;
					idx = 1 - idx;
				}
				else{
					for(auto it: mp2[H]){
						tot += it;
						n--;
						mp1[it].erase(mp1[it].find(H));
					}
					W -= tot;
					idx = 1 - idx;
				}
				if(tot == 0) return false;
			}
			if(n != 0) return false;
			return true;
		};
		if(S % maxw == 0 && check(n, maxw, S / maxw, 0, mp1, mp2)) 
			ans.insert({maxw, S / maxw});
		if(S % maxh == 0 && check(n, S / maxh, maxh, 1, mp1, mp2))
			ans.insert({S / maxh, maxh});
		cout << ans.size() << '\n';
		for(auto t : ans)
			cout << t.first << ' ' << t.second << endl;
	}
	return 0;
}
posted @ 2023-04-16 19:30  P32sx  阅读(12)  评论(0)    收藏  举报