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();
}
}