Educational Codeforces Round 114 (Rated for Div. 2) A~D题解

本场链接:Educational Codeforces Round 114 (Rated for Div. 2)

A. Regular Bracket Sequences

由于只需要构造 \(n\) 种,所以构造第 \(i\) 的时候可以让最左端的是一个长度为 \(i\) 的大括号,后面的可以任意。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
#define x first
#define y second

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int n;scanf("%d",&n);
		forn(i,1,n)
		{
			forn(j,1,i)	printf("(");
			forn(j,1,i)	printf(")");
			forn(j,1,n - i)	printf("()");
			puts("");
		}
	}
	return 0;
}
		

B. Combinatorics Homework

求出:最多构造的个数和最少构造的个数,由于具体形态其实并不重要,不妨调整三个数使得: \(a \geq b \geq c\)。这样构造:AAAABBBBCCCC显然总是个数最多的方案。构造:ABABABABACACAC...这样总是最少的。考虑 \(m\) 是否是可达的:从最多的方案中把一个 \(B/C\)放到开头的 A中去可以导致答案恰好减少一个,所以只要 \(m\) 处于最大值和最小值之间,总是可达的。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
#define x first
#define y second

int a[10];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		forn(i,1,3)	scanf("%d",&a[i]);
		int m;scanf("%d",&m);
		sort(a + 1,a + 3 + 1);reverse(a + 1,a + 3 + 1);
		if(m >= a[1] - a[2] - a[3] - 1 && m <= a[1] + a[2] + a[3] - 3)	puts("YES");
		else puts("NO");
	}
	return 0;
}
		

C. Slay the Dragon

每个问题独立,对于每个问题显然我们只关注: \(a_p \geq x\) 且最小的 \(a_p\) 以及 \(a_p < x\) 且最大的 \(a_p\)

求出对应的 \(p\) 算出答案即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
#define x first
#define y second

const int N = 2e5+7;
ll a[N];

int main()
{
	int n;scanf("%d",&n);
	ll sum = 0;
	forn(i,1,n)	scanf("%lld",&a[i]),sum += a[i];
	sort(a + 1,a + n + 1);a[0] = -1e18;a[n + 1] = 1e18;

	int m;scanf("%d",&m);
	while(m--)
	{
		ll x,y;scanf("%lld%lld",&x,&y);
		int p = lower_bound(a + 1,a + n + 1,x) - a;
		ll res = 2e18;
		if(p <= n)	res = min(res,max(0ll,y - sum + a[p]));
		--p;
		if(p >= 1)	res = min(res,max(0ll,y - sum + a[p]) + x - a[p]);
		printf("%lld\n",res);
	}
	return 0;
}
		

D. The Strongest Build

显然一点:每个位置都取最大值总是一个最牛逼的状态,但是这样的状态不总是可以达到的。如何求出一个可行的答案?考虑遍历答案:每次把当前的答案中的一个还可以减少的位置减一,这样每个状态每次拓展的时候都会获得至多 \(n\) 个新状态。从最开始最牛逼的状态往下遍历求最优解可以对应到求最短路上。这样跑 dijkstra 即可。

时间复杂度:不会,感性理解一下:本来没得限制条件的话一开始就是最大的,但是有了之后最多也就拓展出 \(m+1\) 个状态,虽然单个状态每次拓展的时候会直接拓展出至多 \(n\) 个新状态,但是对整个的复杂度影响不会很大,因为 \(n\) 的值太小了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
#define x first
#define y second

const int N = 2e5+7,M = 17;
int a[M][N],siz[M];

struct Node
{
	int w;
	vector<int> vals;
	Node (vector<int>& oth)
	{
		w = 0;
		vals = oth;
		forn(i,0,vals.size() - 1)	w += a[i + 1][vals[i]];
	}

	bool operator<(const Node& rhs)	const
	{
		if(w != rhs.w)	return w < rhs.w;
		forn(i,0,vals.size() - 1)	if(vals[i] != rhs.vals[i])	return vals[i] < rhs.vals[i];
		return 0;
	}

	bool operator>(const Node& rhs)	const
	{
		if(w != rhs.w)	return w > rhs.w;
		forn(i,0,vals.size() - 1)	if(vals[i] != rhs.vals[i])	return vals[i] > rhs.vals[i];
		return 0;
	}

	bool operator==(const Node& rhs)	const
	{
		if(w != rhs.w)	return 0;
		forn(i,0,vals.size() - 1)	if(vals[i] != rhs.vals[i])	return 0;
		return 1;
	}
};

map<Node,int> st,ban;

int main()
{
	int n;scanf("%d",&n);
	forn(i,1,n)
	{
		scanf("%d",&siz[i]);
		forn(j,1,siz[i])	scanf("%d",&a[i][j]);
	}

	int m;scanf("%d",&m);
	forn(i,1,m)
	{
		vector<int> oth(n);
		for(auto& _ : oth)	scanf("%d",&_);
		Node banp(oth);
		ban[banp] = 1;
	}

	vector<int> best(n);
	forn(i,1,n)	best[i - 1] = siz[i];
	Node STT(best);

	priority_queue<Node,vector<Node>,less<Node>> pq;pq.push(STT);
	while(!pq.empty())
	{
		auto u = pq.top();pq.pop();
		if(st[u])	continue;
		st[u] = 1;
		
		if(!ban.count(u))
		{
			for(auto& _ : u.vals)	printf("%d ",_);
			puts("");
			return 0;
		}

		Node v = u;
		forn(i,0,n - 1)
		{
			if(v.vals[i] == 1)	continue;
			--v.vals[i];
			v.w -= a[i + 1][v.vals[i] + 1] - a[i + 1][v.vals[i]];
			pq.push(v);
			v.w += a[i + 1][v.vals[i] + 1] - a[i + 1][v.vals[i]];
			++v.vals[i];
		}
	}
	return 0;
}
		
posted @ 2021-09-21 21:22  随处可见的阿宅  阅读(197)  评论(0编辑  收藏  举报