codeforces 961(div.2)-A- Diagonals与B1 - Bouquet (Easy Version)

961(div.2)A- Diagonals

由于对角线分布为1~n~1,所以先填中间可容纳最大的,然后填两边,一直填到顶角,并记录填的对角线次数。

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
int n;
int k;
int num;
void slove(int n)
{
	for (int i = n; i >= 1; i--)
	{
		if (k <= 0)
		{
			break;
		}
		if (i == n)
		{
			k -= i;
			num++;
		}
		else {
			k -= i;
			num++;
			if (k > 0)
			{
				k -= i;
				num++;
			}
		}
	}
} 
int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		
		cin >> n;
		cin >> k;
		num = 0;
		slove(n);
		cout << num << endl;
	}

	return 0;
}

961(div.2)B1 - Bouquet (Easy Version)

NO .1 小数替换大数

思路就是从小到大,先找“小数”,然后去找比小数大1的“大数”,然后把小数替换成大数,但是小数有数量,钱有限制,根据此条件去判断能替换几个大数,每把1个小数替换成1个大数,花瓣数量就加1。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n';
#define	int long long
const int N = 2e5 + 10;

signed main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		map<int, int>a;
		vector<pair<int, int>>arr;
		for (int i = 1; i <= n; i++)
		{
			int x;
			cin >> x;
			a[x]++;
		}
		for (auto k : a)		//利用Map排好序后存入vector,first为花瓣,second为数量
		{
			arr.push_back({ k.first,k.second });
		}
		ll ans = 0;
		ll num = 0;
		for (int i = 0; i < arr.size()-1; i++)		//从小到大遍历花瓣种类
		{
			int x = m / arr[i].first;		//能买几个小数
			int y = m % arr[i].first;		//买完小数花瓣后还剩下多少
			if (arr[i+1].first-arr[i].first==1)		//如果下一个正好是现在的"大数"(相差1)
			{
				if (arr[i].second >= x)//如果小数的数量足够
				{
					if (arr[i + 1].second >= min(x, y))		//下面要把小数换成大数,看看能换几个:min(x,y)去找小数个数和所余的最小值,即能换几个小数
					{
						ans = max(ans, arr[i].first * x + min(x, y));	//如果大数的数量够换,就把能换的小数换了
					}
					else {
						ans = max(ans, arr[i].first * x + arr[i+1].second);	//因为大数和小数就差1,所以替换后也就是加1即可,所以加大数的数量就行。	
					}
				}
				else if (arr[i].first * arr[i].second + arr[i + 1].first * arr[i + 1].second > m)//如果小数数量不够且把大数和小数都算上却大于m
				{
					int xx = (m - arr[i].first * arr[i].second) / arr[i + 1].first;	//都选小数后看看还能买几个大数,补上
					int yy = (m - arr[i].first * arr[i].second) % arr[i + 1].first;//补大数后看看还剩多少
					if (arr[i + 1].second - xx >= min(yy, arr[i].second))	//补大数后看看剩下的大数的数量够不够换小数。如果够。能被换的小数的数量是min(...)
					{
						ans = max(ans, m - yy + min(yy, arr[i].second));	//m-yy是都选小数且用大数补后的花瓣数量,加上能被换的小数的数量才是最终的。道理与上一个一样。
					}
					else {		//如果数量不够换,则加上剩下的大数数量。
						ans = max(ans, m - yy + arr[i + 1].second - xx);
					}
				}
				else {		//如果大数和小数都能买上,则最终就是所有的花瓣数
					ans = max(ans, arr[i].first * arr[i].second + arr[i + 1].first * arr[i + 1].second);
				}
			}
			
		}
		for (auto p : arr)		//如果花瓣都相差1以上或者就是去看单买一种花的情况
		{
			if (p.first * p.second <= m)
			{
				ans = max(ans, p.first * p.second);
			}
			else {
				ans = max(ans, p.first * (m/p.first));
			}
		}
		cout << ans << endl;
	}
	return 0;
}

NO.2 滑动窗口,找最大区间和

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n';
const int N = 2e5 + 10;
#define int long long
signed main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		vector<int>a(n);
		for (int i = 0; i < n; i++)
		{
			cin >> a[i];
		}
		sort(a.begin(), a.end());	//从小到大排序
		queue<int>arr;		//用队列进行滑动窗口,要使用单调队列,及队列里的数具有单调性
		ll ans = 0;
		ll num = 0;
		for (int i = 0; i < n; i++)	//遍历花朵
		{
			while (arr.size() && (a[i] - arr.front() > 1 || a[i] + num > m)) {	//当队列里面有数或者相差大于1以及钱不够,则弹出队列的首位
				num -= arr.front();
				arr.pop();
			}
			if (a[i] + num <= m)	//这种情况其实是队列都被弹完了,但是要买的花瓣钱必须得够。
			{
				arr.push(a[i]);
				num += a[i];
				ans = max(ans, num);

			}

		}
		cout << ans << endl;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值