codeforces1203 F1 Complete the Projects (easy version)

本文详细解析了 Codeforces 题目 1203F1 的解题策略,针对不同条件下的最优选择算法进行深入探讨,并附带完整的 C++ 实现代码。通过对比 a1+b1 和 a2+b2 的大小,证明了特定顺序下解的存在性。

传送门:http://codeforces.com/problemset/problem/1203/F1

参考博客:https://blog.youkuaiyun.com/evilwind2000/article/details/99542823?utm_source=app

分两种情况:b>=0的时候十分简单,只要一直取a最小的就行了

b<0的时候,一直取 a+b 较大的,只需证明 a1+b1>a2+b2时候,如果 1 2 这样的顺序不行,那么2 1 也不行

(1)如果r<a1 || r+b1+b2<0  显然不行 

(2)如果r+b1<a2 ,那么由a1+b1>a2+b2,得b2<a1-a2+b1,则r+b2<r+b1+a1-a2<a2+a1-a2=a1,那么肯定是不行的。

#include<bits/stdc++.h>
#define maxl 300010
 
using namespace std;
 
int n,m,ans,r,cnt;
struct node
{
	int a,b;
	bool operator < (const node &b)const
	{
		return this->b<b.b;
	}
}a[maxl],c[maxl];
char s[maxl];
vector <node> b[maxl];
priority_queue <node> q;
bool in[maxl];
 
inline void prework()
{
	scanf("%d",&n);
	scanf("%d",&r);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].a,&a[i].b);
		if(a[i].a<=r)
			q.push(a[i]);
		else
			b[a[i].a].push_back(a[i]);
	}
}
 
inline bool cmp(const node &x,const node &y)
{
	if(x.a+x.b==y.a+y.b)
		return x.a<y.a;
	return x.a+x.b<y.a+y.b;
}
 
inline void mainwork()
{
	node d;int sum=0;ans=0;
	while(!q.empty())
	{
		d=q.top();
		if(d.b<0)
			break;
		q.pop();sum++;
		for(int i=r+1;i<=r+d.b && r+d.b<maxl;i++)
		{
			int l=b[i].size();
			for(int j=0;j<l;j++)
				q.push(b[i][j]);
		}
		r+=d.b;
	}
	if(sum==n)
	{
		ans=1;
		return;
	}
	while(!q.empty())
		c[++cnt]=q.top(),q.pop();
	sort(c+1,c+1+cnt,cmp);
	for(int i=cnt;i>=1;i--)
	if(c[i].a<=r)
		r+=c[i].b,sum++;
	else
	{
		ans=0;
		return;
	}
	if(r>=0 && sum==n)
		ans=1;
}
 
inline void print()
{
	if(ans)
		puts("YES");
	else
		puts("NO");
}
 
int main()
{
	int t=1;
	//scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{ 
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

Codeforces Round 1000 Div. 2 F1 题目 "Counting Is Not Fun (Easy Version)" 中,问题的核心是计算满足特定条件的子数组数量,而这些子数组的元素值与它们在子数组中的位置相关。 ### 题目简述 题目要求找到数组中满足特定条件的子数组数量。具体而言,对于一个长度为 $ n $ 的数组 $ a $,要求统计所有子数组 $ [l, r] $(其中 $ 1 \leq l \leq r \leq n $)的数量,使得对于该子数组内的每个位置 $ i $(相对于子数组的起始点 $ l $ 的偏移),满足 $ a[i] = i - l $。 ### 解题思路 1. **滑动窗口方法**:可以使用滑动窗口的思想来解决这个问题。我们遍历数组,尝试找到尽可能长的连续段,其中每个元素的值等于其相对于当前段起始位置的偏移量。对于每一个起始位置 $ l $,找到最大的 $ r $,使得所有 $ a[i] = i - l $ 对于 $ i \in [l, r] $ 成立。 2. **统计符合条件的子数组数量**:对于每一个满足条件的连续段,长度为 $ len $,则该段内可以形成的子数组数目为 $ len \times (len + 1) / 2 $。这是因为长度为 $ len $ 的连续段可以形成 $ len + (len - 1) + ... + 1 = len \times (len + 1) / 2 $ 个子数组。 3. **遍历数组**:通过遍历数组并维护当前段的起始位置,可以高效地找到所有符合条件的连续段并统计其对应的子数组数量。 ### 时间复杂度 该算法的时间复杂度为 $ O(n) $,因为每个元素最多被访问一次,且没有嵌套循环。 ### 示例代码 以下是一个实现该思路的 Python 示例代码: ```python n = int(input()) a = list(map(int, input().split())) count = 0 i = 0 while i < n: if a[i] != 0: i += 1 continue # 找到最长的连续段 j = i while j < n and a[j] == j - i: j += 1 length = j - i count += length * (length + 1) // 2 i = j print(count) ``` ### 代码说明 1. 首先读取输入的数组。 2. 遍历数组,寻找所有起始位置 $ i $,其中 $ a[i] = 0 $,因为这是可能的子数组起点。 3. 对于每一个起点 $ i $,找到最长的连续段 $ [i, j) $,使得所有元素满足 $ a[k] = k - i $。 4. 根据连续段的长度计算符合条件的子数组数量,并累加到最终结果中。 ### 相关优化 在实现中,需要注意避免重复计算或遗漏某些情况,例如当数组中存在多个连续段时,确保每个段都被正确分割并计算。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值