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 ij1这都是相同的站点。问到达最后一个站点所需的最小代价。

  • 解题思路
    贪心的来看,连续的一段实际上就可以看成一个点,且就是最开始的一个点,因为我们在这一段乘坐都只能达到下一段的开头。所以我们可以把段压缩成点,那么我们就只需要考虑从那个段开始一直乘坐下去即可。注意处理一个特殊情况,即最后一段的开头就是最后一个站点,此时这个段不需要考虑了。

  • 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(a2i1,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;
}
posted @   unique_pursuit  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示