「杂题乱刷」CF1904B

题目链接

CF1904B Collecting Game

题意简述

给你一个由 n 个正整数组成的序列 a 和一个分数。如果你的分数大于或等于 ai,那么你可以将分数增加 ai,并从序列中删除 ai,你需要求出对于每一个 ai 为你的分数时你可以从这个序列中删除数的最大数量。

解题思路

我们可以考虑将询问离线并将数字从小到大排序,然后维护一个指针 l,代表当前数字能到达的数,因为这样维护的话我们会发现,当一个数字比另一个数字大时,那么它所能到达的数字是不可能比比它小的数字小的,因此这样贪心是正确的。

参考代码

#include<bits/stdc++.h>
using namespace std;
long long t,n,sum,l,ans[100010];
struct node{
	long long x,id;
}a[100010];
bool cmp(node x,node y){
	return x.x<y.x;
}
#define forl(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=a;i>=b;i--)
#define lc(x) x<<1
#define rc(x) x<<1|1
#define lowbit(x) x&-x
#define pb push_back
#define pf push_front
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
int main()
{
	IOS;
	cin>>t;
	while(t--)
	{
		cin>>n;
		bool vis[n+1]={0};
		forl(i,1,n)
			cin>>a[i].x,a[i].id=i;
		sort(a+1,a+1+n,cmp);
		sum=0,l=1;
		forl(i,1,n)
		{
			while(l<=i)
			{
				if(!vis[l])
					vis[l]=1,sum+=a[l].x;
				l++;
			}
			if(sum>=a[l].x)
				while(sum>=a[l].x)
				{
					//cout<<l<<endl;
					if(!vis[l])
						vis[l]=1,sum+=a[l].x;
					if(sum<a[l+1].x || l>=n)
					{
						ans[a[i].id]=l-1;
						break;
					}
					l++;
				}
			else
				ans[a[i].id]=l-2;
		}
		forl(i,1,n)
		{
			if(ans[i]==n)
				ans[i]--;
			cout<<ans[i]<<" ";
		}
		cout<<endl;
	}
	QwQ;
}
/*
Hack:
5
1 2 3 7 10
*/
posted @   wangmarui  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示