A.Frog Jumping
题目大意:
意思很简单,对于一个数x = 0进行k次操作,当操作次数为奇数时 x+=a偶数时x-=b。求x
思路:
分k为奇数和偶数的两种情况,奇数时需要 +a,偶数时直接计算即可。
#include<iostream>
#include<stack>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 100010;
int a[N];
int main()
{
int n;
cin >> n;
while (n--)
{
ll a, b, c;
cin >> a >> b >> c;
if (c % 2 == 0) {
cout << (a - b) * (c / 2) << endl;
}
else {
int h = c / 2;
cout << a + (a - b) * h << endl;
}
}
}
B.Disturbed People
题目大意:
一栋公寓中开灯的屋子设为1,不开灯的为0,如果一户人家在两户开灯的人家之间,那他就无法入睡。
求改变的最小次数使得所有户人家都能正常入睡。
思路:
如果a[i] = 0 而且a[i-1] = 1,a[i + 1] = 1,时将 a[i+1] 变为 0并记录次数即可。
#include<iostream>
#include<stack>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 100010;
int a[N];
int main()
{
int n;
cin >> n;
int cnt = 0;
for (int i = 1; i <= n; i++)cin >> a[i];
for (int i = 1; i <= n; i++) {
if (a[i] == 1 && a[i + 1] == 0 && a[i + 2] == 1)
cnt++, a[i + 2] = 0;
}
cout << cnt << endl;
}
C. Good Array
题目大意:
一个序列是good的,当且仅当有一个数是其他数之和,现在你可以去掉一个数,使得这个数组变为good,请输出所有的可能。
思路:
首先将数组递增排序,显然答案肯定是先找到第一大和第二大的数,令第一大的数与前n-1项和作差,利用map寻找符合元素加入答案数组中,再判断第一大的数与第二大的数是否相等再进行判断即可。
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int N = 200010;
struct node {
int x;
int y;
}b[N];
int kk[N];
map<int, int>mp;
bool cmp(node x, node y) {
return x.x < y.x;
}
int main() {
int n;
ll k = 0;
int f = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> b[i].x;
b[i].y = i;
mp[b[i].x]++;
}
sort(b + 1, b + 1 + n, cmp);
int h1 = b[n].x, h2 = b[n - 1].x;
ll ans = 0;
for (int i = 1; i <= n - 1; i++) {
ans += b[i].x;
}
for (int i = 1; i < n; i++) {
if (ans - b[n].x == b[i].x)kk[k++] = b[i].y;
}
if (h1 != h2) {
ans += h1;
ans -= h2;
if (ans - h1 == h2)kk[k++] = b[n].y;
}
else {
if (ans - h1 == h2)kk[k++] = b[n].y;
}
if (k != 0) {
cout << k << endl;
cout << kk[0];
for (int i = 1; i < k; i++) {
cout << ' ' << kk[i];
}
cout << endl;
}
else puts("0");
}
D Cutting Out
题目大意:
给出一个序列,要求你找到其中能切割的最长序列使得切割次数为m,切割是指在原序列中能找到与其相同的数并且将其删除。
思路:
看到题目感觉是一道二分,二分切割次数,首先用map来存数目,在数量中二分,最后一点坑wa了好久,需要对最后二分得到的结果在进行一次check,最后按照次数输出即可。
#include<iostream>
#include<stack>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 200010;
ll a[N];
ll k = 0;
ll n, m;
ll ans[N];
map<ll, ll>mp;
bool check(int x) {
ll sum = 0;
for (int i = 0; i < k; i++) {
sum += (mp[a[i]] / x);
}
if (sum >= m)return true;
else return false;
}
int main()
{
cin >> n >> m;
mp.clear();
for (int i = 1; i <= n; i++) {
ll x;
cin >> x;
if (mp[x] == 0)
a[k++] = x, mp[x]++;
else mp[x]++;
}
sort(a, a + k);
int l = 1, r = n + 1,mid;
while (l < r)
{
mid = l + r + 1>> 1;
if (check(mid))l = mid;
else r = mid - 1;
}
if (check(mid))l = mid;
int t = 0;
//cout << l << mid << r << endl;
for (int i = 0; i <= k; i++) {
while(mp[a[i]] >= l) {
mp[a[i]] -= l;
cout << a[i] << ' ';
if (!--m)return 0;
//cout << a[i];
}
}
return 0;
}
E Thematic Contests
题目翻译:
思路:
用一个map存题目种类,用数组存题目次数,排序 + 离散化,分别枚举每个题目利用二分进行寻找后面的数据。
#include<iostream>
#include<stack>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 200010;
int a[N];
map<int, int >mp;
int main()
{
int n;
cin >> n;
mp.clear();
int k = 0;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (mp[x] == 0)
mp[x] = ++k;
a[mp[x]]++;
}
sort(a + 1, a + k + 1);
ll ans = 0;
/*for (int i = 1; i <= k; i++)
cout << a[i] << ' ' << mp[a[i]];*/
for (int i = 1; i <= n; i++) {
ll sum = 0;
int be = 1;
for (int j = i; j <= n; j *= 2) {
int pos = lower_bound(a + be, a + 1 + k, j) - a;
if (pos == k + 1)break;
sum += j;
be = pos + 1;
}
ans = max(ans, sum);
}
cout << ans << endl;
}
还有一个dp的写法,笑死根本不会写。。看下hz聚聚的代码叭。
https://blog.csdn.net/m0_52348473/article/details/116330832