本場鏈接: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;
}