D4——贪心练习

习题课,无知识点

数列极差问题

题目描述

在黑板上写了N个正整数组成的一个数列,进行如下操作: 每次擦去其中的两个数a和b,然后在数列中加入一个数a×b+1,如此下去直至黑板上 剩下一个数,在所有按这种操作方式最后得到的数中,最大的为max,最小的为min, 则该数列的极差定义为M=max-min。

请你编程,对于给定的数列,计算极差。

输入描述

输入包含多个测试集。每个测试集的第一个数N表示 正整数序列长度(0<=N<=50000),随后是N个正整数。N为0表示输入结束

输出描述

每个结果一行

样例

输入

复制代码
3
1
2
3
0

输出

复制代码
2

代码

cpp 复制代码
#include<iostream>
#include<queue>
using namespace std;
int n,a[50005];
long long c,j;
int main(){
	while(cin>>n&&n!=0){
		priority_queue<int>q;
		priority_queue<int,vector<int>,greater<int> >b;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			q.push(a[i]);
			b.push(a[i]);
		}
		while(q.size()>1){
			int x=q.top();
			q.pop();
			int y=q.top();
			q.pop();
			q.push(x*y+1);
		}
		while(b.size()>1){
			int x=b.top();
			b.pop();
			int y=b.top();
			b.pop();
			b.push(x*y+1);
		}
		cout<<b.top()-q.top()<<"\n";
	}
	return 0;
}

喷水装置(二)

题目描述

有一块草坪,横向长w,纵向长为h,在它的橫向中心线上不同位置处装有n(n<=100000)个点状的喷水装置,每个喷水装置i喷水的效果是让以它为中心半径为Ri的圆都被润湿。请在给出的喷水装置中选择尽量少的喷水装置,把整个草坪全部润湿。

输入描述

第一行输入一个正整数N表示共有n次测试数据。每一组测试数据的第一行有三个整数n,w,h,n表示共有n个喷水装置,w表示草坪的横向长度,h表示草坪的纵向长度。随后的n行,都有两个整数xi和ri,xi表示第i个喷水装置的的横坐标(最左边为0),ri表示该喷水装置能覆盖的圆的半径。

输出描述

每组测试数据输出一个正整数,表示共需要多少个喷水装置,每个输出单独占一行。如果不存在一种能够把整个草坪湿润的方案,请输出0。

样例

输入

复制代码
2
2 8 6
1 1
4 5
2 10 6
4 5
6 5

输出

复制代码
1
2
cpp 复制代码
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
struct qj {
	double a,b;
} q[10005];
bool cmp(qj n,qj m) {
	return n.a<m.a;
}
int n,t,w,h,r,x,num;
int main() {
	cin>>t;
	while(t--) {
		num=0;
		cin>>n>>w>>h;
		double H=h/2.0;
		for(int i=1; i<=n; i++) {
			cin>>x>>r;
			if(r>H) {
				double t=sqrt(r*r-H*H);
				q[++num].a=x-t;
				q[num].b=x+t;
			}
		}
		if(num==0) {
			cout<<0<<"\n";
			continue;
		}
		sort(q+1,q+num+1,cmp);
		int cnt=0,k=0,f=0;
		double pr=0;
		for(int i=1; i<=num; i++) {
			if(pr>=w) {
				break;
			}
			int t=i,ma=q[i].b,ans=i;
			while(q[t].a<=pr&&t<=num) {
				if(ma<q[t].b) {
					ma=q[t].b;
					ans=t;
				}
				t++;
			}
			if(q[ans].a<=pr) {
				cnt++;
				i=ans;
				pr=q[i].b;
			} else {
				cout<<0<<"\n";
				f=1;
				break;
			}
		}
		if(!f) {
			cout<<cnt<<"\n";
		}
	}
	return 0;
}

愤怒的家雀子

题目描述

在森林里有一排树。第i棵树的高度是Di。有一只家雀儿,它在第一棵树上,它只有到最后一棵树的顶端才能找到食物

然而,这只鸟力气比较小,无法直接飞到那里。小鸟如果在第i棵树,那么他可以跳到第i+1,i+2,...,i+k棵树,然后必须休息。而且,向上飞要比向下飞难得多。 如果雏鸟跳到一棵不矮于当前树的树,那么他的劳累值会+1,否则不会累积疲劳值(可以滑翔)。 我们如果在飞翔的过程中有目的地选择小鸟降落的树,这样整个飞行过程就不会那么累。

输入描述

第一行1个整数N表示树的个数(2 <= N <= 10^6);

第二行N个整数分别表示第i棵树的高度D[i];

第三行1个整数Q(1 <= Q <= 25)表示K的个数;

接下来Q行,每行1个整数表示K。

输出描述

输出Q行,每行1个整数表示家雀儿在此K情况下最小化的劳累值。

样例

输入

复制代码
9
4 6 3 6 3 7 2 6 5
2
2
5

输出

复制代码
2
1

提示

K=2时

家雀儿可以从第一棵树向右飞停在第三、五、七、八、九号树上,它的疲劳值是从第三棵树到第五棵树,从第七树到第八树的飞行过程中积累的,也可以停在第三、五、七、九号树上。

代码

cpp 复制代码
#include<iostream>
using namespace std;
int n,d[10000005],q,k;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>d[i];
	} 
	cin>>q;
	while(q--){
		cin>>k;
		int pr=1,sum=0;
		while(pr+k<n){
			int hm=-1,t=pr,ma=-1,t1=pr;
			for(int i=pr+1;i<=pr+k;i++){
				if(d[i]<d[pr]){
					if(hm<d[i]){
						hm=d[i];
						t=i;
					}
				}
				if(d[i]>=ma){
					ma=d[i];
					t1=i;
				}
			}
			if(hm==-1){
				sum++;
				pr=t1;
			}
			else{
				pr=t;
			}
		}
		if(d[pr]<=d[n]){
		    sum++;
		}
		cout<<sum<<"\n";
	}
	return 0;
}
相关推荐
吕小明么39 分钟前
OpenAI o3 “震撼” 发布后回归技术本身的审视与进一步思考
人工智能·深度学习·算法·aigc·agi
大胆飞猪1 小时前
C++9--前置++和后置++重载,const,日期类的实现(对前几篇知识点的应用)
c++
1 9 J1 小时前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
程序员shen1616111 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
夕泠爱吃糖1 小时前
C++中如何实现序列化和反序列化?
服务器·数据库·c++
长潇若雪1 小时前
《类和对象:基础原理全解析(上篇)》
开发语言·c++·经验分享·类和对象
汝即来归1 小时前
选择排序和冒泡排序;MySQL架构
数据结构·算法·排序算法
咒法师无翅鱼2 小时前
【定理证明工具调研】Coq, Isabelle and Lean.
算法
风清云淡_A2 小时前
【java基础系列】实现数字的首位交换算法
java·算法
涵涵子RUSH2 小时前
合并K个升序链表(最优解)
算法·leetcode