Codeforces Round #623 (Div. 2) A~D 题解
A. Dead Pixel
-
题意
给你一个大小为 a × b a\times b a×b的矩形像素格,其中 ( x , y ) (x,y) (x,y)是坏掉的。问你能选取不包括 ( x , y ) (x,y) (x,y)的最大子矩形面积是多少。 -
解题思路
考虑这个点将矩形分成了上下左右四个大矩形。取出最大的面积即可。 -
AC代码
/**
*@filename:A
*@author: pursuit
*@created: 2021-08-20 14:43
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t,n,a,b,x,y;
void solve(){
cout << max(x * b,max(a * (b - y - 1),
max((a - x - 1) * b,a * y))) << endl;
}
int main(){
cin >> t;
while(t -- ){
cin >> a >> b >> x >> y;
solve();
}
return 0;
}
B. Homecoming
-
题意
给你 n n n个站点,其中乘坐bus需要 a a a,乘坐tram需要 b b b,乘坐第 i i i个bus或tram之后可以到达 j j j,需要满足 i … j − 1 i\dots j-1 i…j−1这都是相同的站点。问到达最后一个站点所需的最小代价。 -
解题思路
贪心的来看,连续的一段实际上就可以看成一个点,且就是最开始的一个点,因为我们在这一段乘坐都只能达到下一段的开头。所以我们可以把段压缩成点,那么我们就只需要考虑从那个段开始一直乘坐下去即可。注意处理一个特殊情况,即最后一段的开头就是最后一个站点,此时这个段不需要考虑了。 -
AC代码
/**
*@filename:B
*@author: pursuit
*@created: 2021-08-20 14:53
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*
n个十字路口,每个路口都有公交车或者有轨电车站。
si = A表示第i个十字路口有公交车站,为B则表示有有轨电车。
初始在第1个十字路口,目标达到最后一个。
从i到j,需要[i,j)处的都是同一个类型的。且需要花费a卢布来坐车。
*/
int t;
ll a,b,p;//做bus需要a,做tram需要b,总共有p。
char s[N];
void solve(){
vector<int> v;
int n = strlen(s + 1);
char cur = s[0];
for(int i = 1; i <= n; ++ i){
if(s[i] != cur){
v.push_back(i);
cur = s[i];
}
}
int len = v.size();
if(v[len - 1] == n)v.pop_back(),len --;
cur = s[1];
for(int i = 0; i < len; ++ i){
ll cnt = 0;
if(cur == 'A'){
cnt = 1LL * (len - i + 1) / 2 * a + (len - i) / 2 * b;
cur = 'B';
}
else{
cnt = 1LL * (len - i + 1) / 2 * b + (len - i) / 2 * a;
cur = 'A';
}
if(p >= cnt){
cout << v[i] << endl;
return;
}
}
cout << n << endl;
}
int main(){
scanf("%d", &t);
while(t -- ){
scanf("%lld%lld%lld", &a, &b, &p);
scanf("%s", s + 1);
solve();
}
return 0;
}
C. Restoring Permutation
-
题意
给你一个 b b b数组,其中 b i = min ( a 2 i − 1 , a 2 i ) b_i=\min (a_{2i-1},a_{2i}) bi=min(a2i−1,a2i),请你构造出字典序最小的 a a a。 -
解题思路
首先我们需要知道, b b b数组中的元素是互不干扰的,即它们管辖的元素互不干扰。所以针对每个点,贪心的来看,我们自然是希望将最小值放左边,这样通过 b b b数组我们能确定 n n n个元素,剩下的 n n n个元素我们可以遍历 a a a数组,通过左端元素就找比它大且最小的元素即可。若不能构造,说明无解。 -
AC代码
/**
*@filename:C
*@author: pursuit
*@created: 2021-08-20 15:24
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 200 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t,n,a[N],b[N];
bool vis[N];
void solve(){
for(int i = 1; i <= n; ++ i){
a[2 * i - 1] = b[i];
vis[b[i]] = true;
}
bool flag = false;
for(int i = 1; i <= 2 * n; i += 2){
int temp = a[i];
//找到最小的一个。
while(vis[temp])temp ++;
if(temp > 2 * n){
flag = true;
break;
}
a[i + 1] = temp;
vis[temp] = true;
}
if(flag){
puts("-1");
}
else{
for(int i = 1; i <= 2 * n; ++ i){
printf("%d ", a[i]);
}
puts("");
}
}
int main(){
scanf("%d", &t);
while(t -- ){
scanf("%d", &n);
memset(vis,false,sizeof(vis));
for(int i = 1; i <= n; ++ i){
scanf("%d", &b[i]);
}
solve();
}
return 0;
}
D. Recommendations
-
题意
为每个用户提供n个不相交类别之一的有趣出版物,每个出版物都属于一个类别。我们可以在 t i t_i ti秒找到 i i i类别的出版物,问使得它们出版物数量都不相同的最小时间是多少,其中初始都为 a i a_i ai。 -
解题思路
我们知道,当处于相同数量的时候,我们肯定是让代价小的 + 1 +1 +1。所以我们可以将这些出版物按数量进行排序,然后将相同数量的出版物取出来放到优先队列中维护,然后每轮去掉代价最大的那个即可。当优先队列为空的时候,说明出版物的数量也不同了。达到我们的要求,然后这样依次处理即可。 -
AC代码
/**
*@filename:D
*@author: pursuit
*@created: 2021-08-20 15:38
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 2e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n;
struct node{
int a,t;
//按数量排序。
bool operator < (const node &A){
if(a == A.a){
return t < A.t;
}
return a < A.a;
}
}nodes[N];
priority_queue<int> q;
void solve(){
sort(nodes + 1, nodes + n + 1);
int i = 0;
ll ans = 0,sum = 0,num;
while(!q.empty() || i <= n){
if(q.empty()) num = nodes[i].a;
while(i <= n && nodes[i].a == num){
//将相同值的入队。
q.push(nodes[i].t);
sum += nodes[i ++].t;
}
//相同值得都加1.留下最小的那个。
sum -= q.top(),q.pop();
ans += sum,num ++;//编号+1。
}
printf("%lld\n", ans);
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &nodes[i].a);
}
for(int i = 1; i <= n; ++ i){
scanf("%d", &nodes[i].t);
}
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)