2021暑期牛客多校训练5

本文详细介绍了两种算法问题的解决思路:一是利用递增队列和递减队列求解数组区间极差大于给定值的区间数量;二是计算在随机分布的黑球白球箱子里,确定所有球颜色的最小期望成本。通过对问题的深入剖析,给出了AC代码,并提出了最优策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

K-King of Range

题意:

给一数组,m次询问,每次询问给定k值,问有多少个区间的极差值>k

思路:

对于区间[l,r] ,我们可以先固定右端点r,寻找离r最近的l且满足区间[l,r]极差值>k。

可以考虑在[1,r]内找最大值和最小值计算差值;若大于k,则将位于前面的值更新(下标小的更新,因为要寻找最大的l),若是最大值在前则找次大值代替最大值,若是最小值在前则找次小值代替最小值并重复该步骤,直到差值不大于k

可以用递增队列和递减队列来实现,队列存放a数组的下标。
遍历右端点r(从2开始),将r分别加入到递增队列和递减队列中,再遍历递增递减队列中位于r前面的值并更新l值;

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define fi first
#define se second
#define pb push_back
#define debug(x)   cout<<x<<endl
#define mem(a,b) memset((a),(b),sizeof(a))
const int mod=1000000007;
const double PI = acos(-1);
typedef double db;
#define pep(i,stl) for(auto i:stl)
const int N = 2e6+5;
int n,m,arr[N],add[N],de[N],cnt;
ll ans;
//map<int,int>mp;
int main() {
	cin>>n>>m;
	rep(i,1,n) scanf("%d",&arr[i]);
	while(m--){
		int k;
        ans=0;cnt=0;
		cin>>k;
		int lad=1,rad=1,lde=1,rde=1;
		add[lad]=1;de[lde]=1;
		rep(i,2,n){
			while(lad<=rad and arr[add[rad]]>arr[i]) rad--;
			add[++rad]=i;
			while(lde<=rde and arr[de[rde]]<arr[i]) rde--;
			de[++rde]=i;
			while(lde<=rde and lad<=rad and arr[de[lde]]-arr[add[lad]]>k){
				if(de[lde]<add[lad])
				cnt=de[lde],lde++;
				else
				cnt=add[lad],lad++;
			}
			ans+=cnt;
		}
		cout<<ans<<endl;
	}
	return 0; 
}

B-Boxes

题意:

n个箱子中装着黑球或白球(概率各为1/2),打开箱子的代价为wiw_iwi,可以花费C来得到剩余未打开的箱子中黑球的个数。问要确定所有箱子内球的颜色所要花费的代价的数学期望最小是多少?

思路:

首先花费C来得知黑球的数量,然后通过开一定数目的箱子,来确定所有球的颜色

为了使代价最小,每次先开代价小的箱子,所以将箱子按代价从小到大排序

假设开0个箱子,费用为0;

开1个箱子,费用为w1w_1w1,概率为12n−11\over2^{n-1}2n11;(代价最小的箱子内装的球的颜色和其他箱子里球的颜色不同,共2中情况;n个球总共有2n2^n2n种情况)

开2个箱子,费用为w1+w2w_1+w_2w1+w2,概率为12n−21\over2^{n-2}2n21(前两个箱子有222^222种情况,后n-2个箱子与最后开的箱子颜色肯定不同,因为只有将一种颜色的球全部取完了才能确定其他球的颜色即后n-2个箱子与前两个箱子的情况一一对应,所以共有4种情况;n个球总共有2n2^n2n种情况)

开m个箱子,费用为∑i=1mwi\sum_{i=1}^m w_ii=1mwi,概率为12n−m1\over2^{n-m}2nm1

开n-1个箱子,费用为∑i=1n−1wi\sum_{i=1}^{n-1} w_ii=1n1wi,概率为121\over221

数学期望为C+12n−1∗(w1)+12n−2∗(w1+w2)+...+12∗(∑i−1n−1wi)C+{1\over2^{n-1}}*(w_1)+{1\over2^{n-2}}*(w_1+w_2)+...+{1\over2}*(\sum_{i-1}^{n-1} w_i)C+2n11(w1)+2n21(w1+w2)+...+21(i1n1wi)

最后将所求数学期望与(∑1nwi)(\sum_1^n w_i)(1nwi)作比较,输出较小值。

AC代码:

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define fi first
#define se second
#define pb push_back
#define debug(x)   cout<<x<<endl
#define mem(a,b) memset((a),(b),sizeof(a))
const int mod=1000000007;
const double PI = acos(-1);
typedef double db;
#define pep(i,stl) for(auto i:stl)
const int N = 2e6+5;
int n,m,arr[N],add[N],de[N],cnt;
db c,w[N],sum[N],ans;
int main() {
	cin>>n>>c;
	rep(i,1,n) scanf("%lf",&w[i]);
	sort(w+1,w+1+n);
	rep(i,1,n) sum[i]=sum[i-1]+w[i];
	db t=1;
	pre(i,n,1) t/=2,ans+=sum[i-1]*t;
	if(ans+c<sum[n]) printf("%.6f",ans+c);
	else printf("%.6f",sum[n]);
	return 0; 
}
### 2024 牛客暑期训练营 Sort4 题目解析 #### 题目背景与描述 在2024年的牛客暑期训练营中,Sort4是一道涉及字符串排序和字典序比较的题目。该题目的核心在于通过特定的操作改变给定字符串数组的顺序,并最终使得整个序列达到某种最优状态。 #### 解决方案概述 为了有效解决这个问题,需要理解并应用分治算法以及RMQ(Range Minimum Query)技术来优化查询效率[^3]。具体来说: - **初始化阶段**:读入输入数据并将所有字符串存储在一个列表中。 - **预处理部分**:构建笛卡尔树用于快速查找最小值及其位置;同时记录每个节点的信息以便后续更新操作时能够高效定位目标元素的位置。 - 对于每一次交换请求\( (d_i, p_i) \),判断当前待调整项是否满足条件 \( d_i > p_i \)。如果是,则执行相应的移动动作使新的排列更接近理想解; - 使用自定义比较器对修改后的集合重新排序,确保整体结构仍然保持有序特性不变; - 继续上述过程直至完成全部指令集中的每一条命令为止。 ```cpp #include <bits/stdc++.h> using namespace std; struct Node { int val; int idx; }; bool cmp(Node a, Node b){ return a.val < b.val || (a.val == b.val && a.idx < b.idx); } vector<Node> nodes; int n, q; void buildCartesianTree() {/* ... */ } // 执行单步转换操作 void performOperation(int di, int pi) { if(di > pi){ // 当di大于pi时才会引起字典序变化 swap(nodes[di],nodes[pi]); sort(nodes.begin(), nodes.end(),cmp); } } ``` 此段代码展示了如何基于给定条件实施一次有效的变换,并维持全局秩序不受影响。需要注意的是,在实际竞赛环境中可能还需要额外考虑边界情况以及其他潜在陷阱。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值