【2022ICPC沈阳I题解】【值域线段树+贪心】The 2022 ICPC Asia Shenyang Regional Contest I. Quartz Collection

文章讨论了一道Codeforces的题目,涉及宝石购买的策略。使用贪心算法,首先按第一次购买价格与第二次购买价格之差排序,然后利用值域线段树维护每种宝石的购买情况。在每次价格修改后,通过线段树计算爱丽丝的最小花费。

[I. Quartz Collection](Problem - I - Codeforces)

题意 :

  • 商店里面有n个种类宝石,分别给出第一次购买和第二次购买的价格,只有购买完第一次后才能用第二次购买的价格,两人都想用最少的成本购买宝石
  • 购买的顺序是 : 爱丽丝先买一块石英,然后鲍勃和爱丽丝轮流买两块,直到只剩下一块。还没有收集到所有类型的石英的人买了最后一块
  • 然后m次修改操作,修改某一种类宝石第一次购买和第二次购买的价格,每轮修改后输出爱丽丝的最小花费

分析 :

STEP 1 .贪心

我们先用贪心去想,假设我们都是选择第一次购买的价格,设总和是sum1,那么考虑i物品选择第二次购买就有收益为 A[ i ] - B[ i ] (第一次价格减第二次价格),那么我们尽可能令 A[i] - B[i] 最小
-初步思路: 所以把A[ i ] - B[ i ]排序 ,根据购买的顺序,小于0的数是我连着拿两个,他拿两个(尽量拿)而大于0的数,是我拿一个数,回去拿一个Bob买过的(尽量不拿)

STEP2. 值域线段树求解:

什么是值域线段树:
线段树里面存区间和在区间内的数的个数

那么对于每次修改,我们拿的位置是确定的,我们用值域线段树维护sum[4],分别表示从i号位相隔4个位置的和(例如 1 2 3 4 5 6 7 3 2 ,sum[0] = 1 + 5 + 2),那么对于Bob ,小于0区间的sum[2]+sum[3] 就是他取的值,大于0的部分需要根据小于0的奇偶性来判别

关键代码如下:

ll ask(ll ans){
   
   
	Tree a1 = seg.ask(1,-100000,0);
	Tree a2 = seg.ask(1,1,100000);
	ans -= a1.sum[1] + a1.sum[2];(负数间隔两个取最优)
	if(a1.sz%2==0){
   
   
		ans -= a2.sum[1] + a2.sum[3]; (正数间隔1个取最优)
	}
	else ans -= a2.sum[0] + a2.sum[2];
	return ans;
}

AC 代码:

CF AC代码

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
typedef long long ll;

int A[N],B[N]; 
struct Tree{
   
   
	int l=0,r,sum[4],sz;
};
void add_tr(Tree & tr,Tree & tr1){
   
   
	int siz = tr.s
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值