本场链接: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
",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;
}