Codeforces Round #521 Div.3(A-E)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值