Codeforces Round #679 (Div. 2, based on Technocup 2021 Elimination Round 1)
A
给定\(n\)个数分别为\(a_1,a_2,...,a_n\),构造出一组\(b_1,b_2,...,b_n\)使得\(a_1 \times b_1 + a_2 \times b_2 + ... + a_n \times b_n = 0\) \((a_i\)和\(b_i\)必须是非\(0\)的数且不超过\(100)\) 且\(n\)为偶数。
从\(n\)为偶数作为切入点,直接输出\(a_{i+1}\) 和 \(-a_i\),使得\(a_i \times a_{i + 1} + a_{i + 1} \times -a_i = 0\)。同理,输出\(-a_{i + 1}\)和\(a_i\)也可。
#include <bits/stdc++.h>
using namespace std;
const int N = 100 + 20;
int n;
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%d", &n);
for(int i = 1; i <= n; i += 2)
{
int x, y;
scanf("%d%d", &x, &y);
printf("%d %d ", -y, x);
}
puts("");
}
//system("pause");
return 0;
}
B
对于一个\(n \times m\)的矩阵,给出它每行的顺序和它每列的顺序,还原这个矩阵。
因为矩阵里的数一定是不重复的从\(1\)到\(n \times m\)的数,对于每个二维坐标,记录每个数的行和列,然后反过来用二维数组的行列对应这个值,输出即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 500 + 20;
int r[N * N], c[N * N], a[N][N];
int n, m, x;
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j)
scanf("%d", &x), c[x] = j;
for(int i = 1; i <= m; ++ i)
for(int j = 1; j <= n; ++ j)
scanf("%d", &x), r[x] = j;
for(int i = 1; i <= n * m; ++ i) a[r[i]][c[i]] = i;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= m; ++ j)
printf("%d%c", a[i][j], j == m ? '\n' : ' ');
}
//system("pause");
return 0;
}
C
给定\(n\)个数,和\(6\)个基准数,对于\(n\)个数中的每一个,必须选择\(6\)个数中的一个作差,使得到的\(n\)个差值中最大差值和最小差值的差最小。
将\(n\)个数中每一个和\(6\)个基准数都做一下差,并标记一下这是第\(i\)个数与基准数得到的差,将这个差从小到大排序,然后双指针扫序列,当双指针区域里包含\(n\)个数得到的差\((\)每个数至少\(1\)个\()\)时,并且这个区域不能再缩小时,统计答案,扫完一遍序列即可得到最优解。
写法:左指针每次固定右移,右指针往右扩展。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 1e5 + 20;
int n, a[7], b[N];
int cnt[N], q;
void add(int x)
{
++ cnt[x];
if(cnt[x] == 1) ++ q;
}
void rem(int x)
{
-- cnt[x];
if(cnt[x] == 0) -- q;
}
int main()
{
for(int i = 1; i <= 6; ++ i) scanf("%d", &a[i]);
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) scanf("%d", &b[i]);
vector<pii> vec;
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= 6; ++ j)
vec.push_back(make_pair(b[i] - a[j], i));
sort(vec.begin(), vec.end());
int res = 1e9;
int l = 0, r = -1;
while(l < 6 * n)
{
while(r + 1 < 6 * n && q != n) add(vec[++ r].second);
if(q == n) res = min(res, vec[r].first - vec[l].first);
rem(vec[l ++].second);
}
printf("%d\n", res);
//system("pause");
return 0;
}
D
给定\(n\)件物品,价格分别为\(1,2,...,n\),给定\(2 \times n\)次操作:
\(1:+\) 将一件物品放置到货架上
\(2: - x\) 将物品\(x\)卖出
卖出物品的规则为每次只能售出价格最低的物品,请根据操作还原放置物品的顺序。
对于每一次卖出,一定是选择最近的最近的放置,这次放置的限制比较小,这样选取答案一定是最优。
使用栈去维护这些操作,每次\(+\)操作,将这是第几个放入和值的下限\((\)下限不能被取到\()\),初始化下限为0.
每次\(-\)操作,如果栈中已经没有元素或者当前栈顶的下限 \(>=\)这个值,则不合法,直接输出NO.
如果可以取出,就给栈顶元素位置填上当前取出的数,并对新栈顶修改下限,下限为当前取出的\(x\)和原来下限的最大值。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 20;
int res[N],cnt;
struct zt
{
int pos, val;
};
stack<zt> s;
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= 2 * n; ++ i)
{
char op[2];
int x;
scanf("%s", op);
if(*op == '+') s.push({++ cnt, 0});
else if(*op == '-')
{
scanf("%d", &x);
if(s.empty() || x <= s.top().val)
{
printf("NO\n");
return 0;
}
res[s.top().pos] = x;
s.pop();
if(!s.empty()) s.top().val = max(s.top().val, x);
}
}
printf("YES\n");
for(int i = 1; i <= n; ++ i) printf("%d ", res[i]);
puts("");
//system("pause");
return 0;
}
E
每次施放技能,可以对敌人造成\(a\)点伤害,在接下来的\(c\)秒时间内,每秒敌人可以恢复\(b\)点血,技能冷却时间为\(d\)秒,问可以击杀敌人的最大血量是多少,如果可以击杀任意血量的敌人,输出\(-1\).
首先考虑输出\(-1\)的情况,对于一次施放技能来说,如果总恢复血量\(b \times c\)都不如伤害\(a\)高,那么显然不论\(d\)冷却有多久,都可以通过很多次的技能来击杀任意血量的怪物。
故当\(a > b \times c\) ,答案一定是\(-1\).
考虑其他情况,当\(a >= b \times c\),则击杀怪物血量一定有上限,在先不考虑第一次施放技能的前提下,为了求出可以击杀的最大血量,总共可以让怪物恢复的时间为 \(t = a / b\),在这段时间里,可以施放技能的次数为\(k = t / d\),加上第一次施放技能总共打掉的血量为\(a \times (k + 1)\),总共回复的血量为\(k \times d \times b + (k - 1) \times d \times b+ ... + d \times b = b \times k \times (k + 1) \times d / 2\).
故答案为\[ ans = a \times (k + 1) - b \times k \times (k + 1) \times d / 2 \]
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL a, b, c, d;
int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
if(a > b * c) printf("-1\n");
else
{
LL t = a / b;
LL k = t / d;
LL res = a * (k + 1) - b * d * k * (k + 1) / 2;
printf("%lld\n", res);
}
}
//system("pause");
return 0;
}
2020.11.17