Educational Codeforces Round 105(Rated for div2)

本场链接:https://codeforces.com/contest/1494

A. ABC String

https://codeforces.com/contest/1494/problem/A
大意:给出只含有A,B,C的字符串,其中A,B,C可以转换成’(‘或‘)’,并且相同字符只能转换成相同的括号,问全部转换后得到的括号匹配是否合法。
思路:首先第一个必须是’(’,最后一个必须是‘)’,否则不可能。求出对应的字符后,那么考虑剩下的字符转换成’(’,还是’)’,转换完后就是括号匹配问题了(可以用栈来求)。

#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 500005;
const ll ds = 1e15+7;
//const double p1 = 3.141592653589793238462643383;
 
using namespace std;
 
 
void solve()
{
	//getchar();
	int n,flag = 0;
	char s[55],t[55];
	int cnt[55];
	cin >> s;
	n = strlen(s);
	for(int i = 0; i <= 30; i++) t[i] = ' ';
	if(s[0] == s[n-1]) {
		puts("NO");
		return;
	}
	int l = 0;
	int k = s[0]-'A';
	int k1= s[n-1]-'A';
	t[k] = '(';
	t[k1] = ')';
	int xb = -1;
	for(int i = 0; i < n; i++){
		k = s[i]-'A';
		if(t[k] == ' ') t[k] = '(',xb=k;
	}
	//判断括号是否合法
	for(int i = 0; i < n; i++){
		int k = s[i]-'A';
		if(t[k] == '(')l++;
		else l--;
		if(l < 0) {
			l = -100;
			break;
		}
	}
	if(l == 0) flag = 1;
	if(xb != -1 && l != 0){
		t[xb] = ')';
		l = 0;
		for(int i = 0; i < n; i++){
			int k = s[i]-'A';
			if(t[k] == '(')l++;
			else l--;
			if(l < 0) {
			l = -100;
				break;
			}
		}
	}
	if(l == 0) flag = 1;
	if(flag) puts("YES");
	else puts("NO");
}
 
int main()
{
	int t;
	cin >> t;
	while(t--){
		solve();
	}
	return 0;
}

B. Berland Crossword:暴力

https://codeforces.com/contest/1494/problem/B
大意:给出一个n*n的白格子方正,同时约定最上,右,下,左有多少个黑格子,问是否存在。
思路:看图可以发现如果四个角中的某个角放了格子,那么相邻的边就会同时增加一个黑格子,所有枚举每个角上的格子放不黑格子,总共(2^2)*4中情况。

#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 500005;
const ll ds = 1e15+7;
//const double p1 = 3.141592653589793238462643383;
 
using namespace std;
 
int n;
bool check(int u,int r,int d,int l)
{
	if(u < 0 || r < 0 || d < 0 || l < 0)
		return false;
	if(u > n-2 || r > n-2 || d > n-2 || l > n-2)
		return false;
	return true;
}
 
void solve()
{
	int u,r,d,l;
	int u1,r1,d1,l1;
	u1 = r1 = d1 = l1 = 0;
	cin >> n >> u >> r >> d >> l;
	int flag = 0;
	for(int i = 0; i <= 1; i++){
		for(int j = 0; j <= 1; j++){
			for(int k = 0; k <= 1; k++){
				for(int L = 0; L <= 1; L++){
					u1=u,r1=r,d1=d,l1=l;
					if(i) u1--,l1--;
					if(j) u1--,r1--;
					if(k) r1--,d1--;
					if(L) l1--,d1--;
					//cout << u1 << " " << r1 << " " << d1 << " " << l1 <<"\n";
					if(check(u1,r1,d1,l1)){
						flag = 1;
					}		
				} 
			}
		}
	} 
	if(flag) puts("YES");
	else puts("NO");
}
 
int main()
{
	int t;
	cin >> t;
	while(t--){
		solve();
	}
	return 0;
}

C. 1D Sokoban:二分

https://codeforces.com/contest/1494/problem/C
大意:给定n个箱子的位置,m个特殊位置的位置,人的起点在0,问最多能把多少个箱子推到特殊位置上。
思路:
1)在零右边的箱子只能往右边推,在零左边的箱子只能往左边推。
2)所有将箱子和特殊位置分为大于零和小于零两部分来求解。
3)以右边为例,枚举每个特殊位置,将当前特殊位置前面的所有箱子推到一起,用二分找出有多少个箱子(因为从零开始,所以即在a中大于b[i]的有多少个),假设是xb个,然后当最右边的箱子到了当前特殊位置的时候停,看[i-xb+1,xb]有多少个特殊位置,同样可以二分求。因为可能特殊位置上本来就放了箱子,所有同时还要加上当前特殊位置之后有的特殊位置中有几个特殊位置放了箱子。

#include <bits/stdc++.h>
#define ull unsigned long long
#define ll long long
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 500005;
const ll ds = 1e15+7;
//const double p1 = 3.141592653589793238462643383;

using namespace std;

vector<int>a,b,aa,bb;
map<ll,ll>mp;
void solve()
{
	mp.clear();
	a.clear(),aa.clear(),b.clear(),bb.clear();
	int n,m,x,n1,n2;
	cin >> n >> m;
	n1 = n2 = 0;
	for(int i = 0; i < n; i++) {
		cin >> x;
		if(x > 0) a.push_back(x);
		else aa.push_back(abs(x));
		mp[x] = 1;
	}           
	sort(aa.begin(),aa.end());
	for(int i = 0; i < m; i++){
		cin >> x;
		if(x > 0) {
			b.push_back(x);
			if(mp[x]) n1++;
		}
		else {
			bb.push_back(abs(x));
			if(mp[x]) n2++;
		}
	}
	sort(bb.begin(),bb.end());
	int len1 = 0,q,ans1=0,ans2=0;
	if(b.size() && a.size()){
		int nn = b.size(),len;
		for(int i = 0; i < nn; i++){
			if(mp[b[i]]) n1--;
			int xb = upper_bound(a.begin(),a.end(),b[i])-a.begin();
			int pos = upper_bound(b.begin(),b.end(),b[i]-xb)-b.begin();
		//	cout << xb << " " << pos << endl;
			ans1 = max(ans1,i+1-pos+n1);
		} 
		//cout << ans1 << endl;
	}
	if(bb.size() && aa.size()){
		int nn = bb.size(),len;
		for(int i = 0; i < nn; i++){
			if(mp[-bb[i]]) n2--;
			int xb = upper_bound(aa.begin(),aa.end(),bb[i])-aa.begin();
			int pos = upper_bound(bb.begin(),bb.end(),bb[i]-xb)-bb.begin();
			ans2 = max(ans2,i+1-pos+n2);
		} 
		//cout << ans2 << endl;
	}
	cout << ans1+ans2 <<endl;
}

int main()
{
	int t;
	cin >> t;
	while(t--){
		solve();
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值