Codeforces Round 860 (Div. 2)
Codeforces Round 860 (Div. 2)
Date: 04/08/2023
A|Showstopper
Brief: 两组数
Data:
Solution: 【简单思维题】
发现只需考虑当把大的放在一边,小的放在另一边时的可行性。
题解提到一个比较重要的思想:交换操作大于等于
Complexity:
Review: -
State: AC.
Code:
#define Justanaaaaame
#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 110
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
int a[MAXN], b[MAXN];
for (int i = 1 ; i <= n ; ++i)
cin >> a[i];
for (int i = 1 ; i <= n ; ++i)
cin >> b[i];
for (int i = 1 ; i <= n ; ++i)
if (a[i] < b[i])
swap(a[i], b[i]);
bool flag = true;
for (int i = 1 ; i < n ; ++i)
if (a[i] > a[n] || b[i] > b[n])
{
flag = false;
break;
}
if (flag)
cout << "Yes\n";
else
cout << "No\n";
}
}
B|Three Sevens
Brief:
Data:
Solution: 【简单思维题】【构造】
一个比较重要的思想:倒序考虑。
倒序维护出现过的人,在每一天找一个没出现过的人即可。
Review: 实现时在循环里声明大数组TLE,放全局变量AC:声明有复杂度QAQ(滚去学 cpp 惹~
State: AC.
Code:
#define Justanaaaaame
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
#define MAXN 50010
vector <int> v[MAXN];
bool vis[MAXN];
int ans[MAXN];
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
int m;
cin >> m;
for (int i = 1 ; i <= m ; ++i)
{
v[i].clear();
int n;
cin >> n;
for (int j = 1 ; j <= n ; ++j)
{
int t;
cin >> t;
v[i].push_back(t);
vis[t] = false;
}
}
bool flag;
for (int i = m ; i ; --i)
{
flag = false;
for (const auto &x : v[i])
if (!vis[x])
{
vis[x] = true;
ans[i] = x;
flag = true;
}
if (!flag)
break;
}
if (flag)
{
for (int i = 1 ; i <= m ; ++i)
cout << ans[i] << ' ';
cout << "\n";
}
else
{
cout << "-1\n";
}
}
return 0;
}
C|Candy Store
Brief:
Data:
Solution: 【数学】
Observation 1: 贪心地让当前的标签覆盖更多的袋子最优;
Observation 2:
Observation 3:
综上,只需从前往后判断新加入的是否满足
Review: 实际上离结论已经很近了,然而……
State: -> AC.
Code:
#define Justanaaaaame
#include <iostream>
using namespace std;
#define int long long
int gcd(int a, int b)
{
while(a ^= b ^= a ^= b %= a);
return b;
}
int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
int ans = 1;
int a1, b1;
cin >> a1 >> b1;
int g = a1 * b1, l = b1;
for (int i = 2 ; i <= n ; ++i)
{
int a, b;
cin >> a >> b;
g = gcd(g, a * b);
l = lcm(l, b);
if (g % l)
{
++ans;
g = a * b;
l = b;
}
}
cout << ans << '\n';
}
}
D|Shocking Arrangement
Brief: 给定整数序列,满足和为
Data:
Solution: 【构造】【dp】
Observation 1: 左式可以写成
Observation 2: 只需满足
综上,只需当前缀和
另外,注意到全为
Review: 关键在于公式的转换。注意max和min的性质。复健基本模型。
State: AC.
Code:
#define Justanaaaaame
#include <iostream>
using namespace std;
#define MAXN 300010
int np, pos[MAXN];
int nn, neg[MAXN];
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
nn = 0;
np = 0;
int n;
cin >> n;
for (int i = 1 ; i <= n ; ++i)
{
int t;
cin >> t;
if (t >= 0) pos[++np] = t;
else neg[++nn] = t;
}
if (nn == 0)
{
cout << "No\n";
continue;
}
cout << "YES\n";
long long prefsum = 0;
for (int i = 1 ; i <= n ; ++i)
{
if (prefsum > 0)
{
prefsum += neg[nn];
cout << neg[nn--] << ' ';
}
else
{
prefsum += pos[np];
cout << pos[np--] << ' ';
}
}
cout << '\n';
}
return 0;
}
E|Multitest Generator
Brief: 定义test: 数列的第一个数是长度-1,multitest: 数列第一个数是能将后面的数划分成test的数量。给出一列数,问对于
Data:
Solution: 【dp】
Observation 1: 答案只可能是
Observation 2: 判断为
Observation 3: 现在只需要考虑何时为
(1) 可以覆盖,则只需更改第一个数为test数量;
(2) 不能覆盖,那么只需求出最大可能的test数,小于该值的也一定可行,因为可以修改第二个值,使得其多覆盖任意多个test。那么问题变为如何计算修改一次后最大可能的test数。考虑 dp,如果修改第二个数,test数量为之后可覆盖的最长链+1;如果不修改第二个数,答案为 dp[a[i] + i + 1] + 1
.取 max 即可。和第一个数比较大小,若第一个数小于等于这个数,那么答案为
Review: -
State: AC.
Code:
#define Justanaaaaame
#include <iostream>
#include <cstring>
using namespace std;
#define MAXN 300010
int a[MAXN];
int go[MAXN];
bool able[MAXN];
int len[MAXN];
int dp[MAXN]; // 第 i 位后修改1次的最长链
int ans[MAXN];
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
memset(able, 0, sizeof(bool) * (n+5));
memset(len, 0, sizeof(int) * (n+5));
memset(dp, 0, sizeof(int) * (n+5));
for (int i = 1 ; i <= n ; ++i)
{
cin >> a[i];
go[i] = i + a[i] + 1;
if (go[i] > n + 1)
go[i] = n + 2;
}
able[n + 1] = true;
int maxlen = 0;
for (int i = n ; i ; --i)
{
able[i] = able[go[i]];
len[i] = len[go[i]] + 1;
if (able[i])
maxlen = max(maxlen, len[i]);
dp[i] = max(dp[go[i]] + 1, maxlen + 1);
}
for (int i = n - 1 ; i ; --i)
{
if (able[i + 1])
{
if (a[i] == len[i + 1])
ans[i] = 0;
else
ans[i] = 1;
}
else
{
if (dp[i + 1] >= a[i])
ans[i] = 1;
else
ans[i] = 2;
}
}
for (int i = 1 ; i < n ; ++i)
cout << ans[i] << ' ';
cout << '\n';
}
}
F|Gifts from Grandfather Ahmed
State: 咕咕咕