Codeforces Round 1083 (Div. 2) (A~D)
前言
准备春招了,写写CF练练手,感觉这几题有点水,可能难度都在后面
A. Simons and Making It Beautiful
题意是最多交换一次,使得 \(i=max({r1,r2,…,ri})\) 尽可能小,把最大的数放在第一位就行。
int a[N], b[N];
void solve(){
cin >> n;
int mx = 0;
int cnt = 0;
for(int i = 1; i <= n; i++) {
cin >> a[i];
if(a[i] == n) {
swap(a[i], a[1]);
}
}
for(int i =1 ; i <= n; i++) {
cout << a[i] << " ";
}
cout << endl;
}
B. Simons and Cakes for Success
题意是找出最小的正整数 \(k\),使得 \(n\) 能整除 \(k^n\)。
只要保证每个质因子都出现过,这样幂次上去,每个质因子都会出现 \(n\) 次,也就一定能被整除了。
void solve(){
cin >> n;
int sum = 1;
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
sum *= i;
while(n % i == 0) {
n /= i;
}
}
}
cout << sum * n << endl;
}
C. Simons and Posting Blogs
观察可以发现,在发布一个博客时候,这行越靠后的数,在序列\(Q\)中越靠前,同时先发布的数字会被后发布的相同数字覆盖。
因此每行可以倒过来存,同时只记录每个数字第一次出现。例如 \(3,6,4,3,1,1,5,4\) 可以看作 \(4, 5, 1, 3, 6\) 。
每次从还没发布的博客中,选出一个博客 \(i\),使得它贡献的字典序最小。对于其他未选中的博客,去掉已经出现过的数字。模拟即可。
int a[3001][3001];
void solve(){
cin >> n;
vector<vector<int>> s(n + 1);
for(int i = 1; i <= n; i++) {
cin >> a[i][0];
map<int, int> flag;
for(int j = a[i][0]; j >= 1; j--) {
cin >> a[i][j];
}
for(int j = 1; j <= a[i][0]; j++) {
if (flag[a[i][j]] == 0) {
flag[a[i][j]] = 1;
s[i].push_back(a[i][j]);
}
}
}
map<int, int> flag;
map<int, int> g;
vector<int> ans;
for (int i = 1; i <= n; i++) {
int mi = -1;
vector<int> best;
for (int i = 1; i <= n; ++i) {
if (flag[i]) continue;
vector<int> cur;
for (int x : s[i]) {
if (!g[x]) cur.push_back(x);
}
if (mi == -1 || cur < best) {
best = cur;
mi = i;
}
}
flag[mi] = true;
for (int x : best) {
ans.push_back(x);
g[x] = true;
}
}
for(auto i : ans) {
cout << i << " ";
}
cout << endl;
}
D. Simons and Beating Peaks
题目要求数组中没有任何一个元素大于其相邻的两个元素,即不能有峰值。所以数组只能先单调递减,再单调递增、或者只单调递减、或只单调递增。
显然最大值 \(K\) 永远不可能被删除,那避免让\(K\)成为峰值,只能把\(K\)左侧或者右侧的数删光。于是我们有以下两种操作:
- 让\(K\)成为最左端,把左侧的数删光,这要求\(K\)右侧至少有一个数。
- 同理,让\(K\)成为最右端,把右侧的数删光。
固定好最大值之后,就可以在剩下的区域中固定次大值。一步步固定完所有数。
可以发现删数时,每次取左侧或者右侧的最大值的过程,可以用笛卡尔树解决。
把数组构建成笛卡尔树,然后进行树形\(DP\)即可。
int a[N];
int l[N], r[N], sz[N];
void dfs(int u) {
if (u == 0) return;
sz[u] = 1;
if (l[u]) {
dfs(l[u]);
sz[u] += sz[l[u]];
}
if (r[u]) {
dfs(r[u]);
sz[u] += sz[r[u]];
}
};
int dfs2(int u) {
if (u == 0 || sz[u] == 1) return 0;
int ans = 1e9;
if (r[u]) {
ans = min(ans, sz[l[u]] + dfs2(r[u]));
}
if (l[u]) {
ans = min(ans, sz[r[u]] + dfs2(l[u]));
}
return ans;
};
void solve() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
l[i] = r[i] = sz[i] = 0;
}
vector<int> st;
for (int i = 1; i <= n; i++) {
int lst = 0;
while (!st.empty() && a[st.back()] < a[i]) {
lst = st.back();
st.pop_back();
}
if (!st.empty()) {
r[st.back()] = i;
}
l[i] = lst;
st.push_back(i);
}
int rt = st[0];
dfs(rt);
cout << dfs2(rt) << endl;
}
有帮助到你的话点个赞吧~

浙公网安备 33010602011771号