2023.10.24 第一次训练赛(ABC306)

文章介绍了编程中的几个问题,涉及基础语法如for循环处理字符串,使用`pow`函数的注意事项,以及算法如动态规划和STL容器`multiset`的应用。作者反思了对数据类型理解的不足和算法实现中的细节错误。
摘要由CSDN通过智能技术生成

在这里插入图片描述

A题

在这里插入图片描述
这题就直接一个for循环将给定字符串中的字符输出两次即可

#include<iostream>
using namespace std;

int main()
{
  string str;
  int n;
  cin >> n >> str;
  for(auto x : str) 
  {
    for(int i = 0 ;i < 2; i ++) cout << x;
  }
  return 0;
}

B题

在这里插入图片描述
刚开始一看是个简单题,我就直接用#include<cmath>里的pow函数结合一个for循环直接模拟2 i 次幂递增过程,结果一直 WA,改了好久都没过,直到心态炸裂。直到比赛结束,大佬提醒我 pow函数的参数和返回值的是浮点型,而且我一直以为long long int那肯定是264,但其中有一位是符号位,只能开unsigned long long,不然也会溢出。还是我太粗心了,以后要多注意这类函数的用法和各种数据类型的范围

#include<iostream>
#include<cmath>
using namespace std;

const int N = 65;

int main()
{
  unsigned long long res = 0, temp = 1;
  for(int i = 0 ;i < 64; i ++)
  {
    int x;
    cin >> x;
    res += x * temp;
    temp *= 2;
  }
  cout << res << endl;
  return 0;
}

C题

在这里插入图片描述
这道题考的是一个对应关系,即记录每个数出现第二次时的位置,再通过该位置进行排序,最后根据该序列的位置大小排序后,输出原先每个位置对应的数值,因此我们可以用pair<int,int>来表示该位置与数值的关系(当时打到1小时55分钟才勉强写出来,一直卡到 a[j++] = {i, x} 这个地方,当初写成了 a[i] = {i, x} 导致下标可能不连续,以至于一直WA),找个借口,那天B题没写出来,心态不好

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1E5 + 10;

int q[N], n, x;
pair<int,int> a[N];

int main()
{
  cin >> n;
  for(int i = 0, j = 0; i < n * 3; i ++)
  {
    cin >> x;
    q[x] ++;
    if(q[x] == 2) a[j ++] = {i, x};
  }
  
  sort(a, a + n);
  for(int i =0 ;i < n ;i ++) cout << a[i].second << " ";
  return 0;
}

D题

在这里插入图片描述
在AcWing上学了两月算法,刷了很多道dp题,虽然代码很简单,但还是不太会写,可能是我只会记忆模板吧

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 3E5 + 10;

int x[N], y[N], n;
long long int f[N][2]; //f[i][j]: 代表第i餐,身体状况为j : 0表示healthy, 1表示upset

int main()
{
    cin >> n;
    for(int i = 1 ;i <= n ;i ++) cin >> x[i] >> y[i];
    
    //第一餐需要特判
    if(x[1]) //有毒
    {
        f[1][1] = max(0, y[1]);  // 。。
    }
    else //解毒
    {
        f[1][0] = y[1]; // 。。
    }
    
    for(int i = 1; i <= n ;i ++)
    {
        if(x[i]){ // 。。
            f[i][0] = f[i - 1][0];
            f[i][1] = max(f[i - 1][0] + y[i], f[i - 1][1]);
        }
        else{  // 。。
            f[i][0] = max(f[i - 1][1] + y[i], max(f[i - 1][0], f[i - 1][0] + y[i]));
            f[i][1] = f[i - 1][1];
        }
    }
    
    cout << max(f[n][1], f[n][0]) << endl; // .......
    return 0;
}

E题

在这里插入图片描述
此题用到了 STL 里面的 multiset ,不了解的可以先去看看这篇博客 multiset的用法,还有就是用到了#define int long long一种独特的定义long long 的方式,int main() .... return 0变成signed main() ...

#include<iostream>
#include<algorithm>
#include<set>
#define int long long 
#define fast ios::sync_with_stdio(false);cin.tie(0);

using namespace std;
const int N = 5e5 + 5;

multiset<int>s, t;
int w[N];
int n, k, q;

void solve()
{
    cin >> n >> k >> q;
    for (int i = 1; i <= n; i++)
    {
        if (i <= k)
            s.insert(0);  //前K大的数
        else
            t.insert(0); //其余的数
    }
    
    int ans = 0; //结果
    
    while (q--) //q次询问
    {
        int x, y;
        cin >> x >> y;
        
        //w[i]是一个标记数组,i表示表示要修改值的位置,w[i]表示要修改的值
        
        if (s.find(w[x]) != s.end()) //在集合s中找到了原来x位置的值,没找到返回end
        {
            s.extract(w[x]); 
            ans -= w[x];
        }
        else  //没找到
        {
            t.extract(w[x]);
        }

        w[x] = y;
        s.insert(w[x]);
        ans += w[x];

        //为如果当前修改的值是在t集合里面
        //将修改过的值加到直接s中可能会是集合s的元素大于k
        //所有应该判断一下,我试试 if 应该也可以
        if (s.size() > k) 
        {
            auto it = *s.begin();  //将最小的数拿到t集合中去
            ans -= it;
            s.extract(it);
            t.insert(it);
        }

        while (s.size() && t.size() && *s.begin() < *t.rbegin())  //一个正向,一个逆向,s, t默认按升序排序
        {  
            //若s集合中的最小值 < t集合中的最大值,
            //即还可以通过s集合和t集合中元素的互换使得s集合元素的总和变大
            
            int m1=*s.begin();    //每次都能拿出s集合中最小的元素
            int m2=*t.rbegin();  //每次都能拿出t集合中最大的元素
            
            //相当于交换,大的放入s中,小的放入t中
            s.extract(m1);
            t.extract(m2);
            s.insert(m2);
            t.insert(m1);
            
            //增加的差值
            ans += m2 - m1; 
        }
        cout << ans << endl;  //输出
    }
}

signed main()
{
    fast;
    int tt = 1;
    //cin >> tt;
    while (tt--)
    {
        solve();
    }
}

F题

在这里插入图片描述

G题

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leisure-pp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值