25.5.20学习总结

做题思路

数列分段 Section IIhttps://www.luogu.com.cn/problem/P1182 正如题目所说,我们需要得到一个最小的最大段的值,可能有人将注意力放在分段上,事实上,我们更多的应该关注结果。这是一道二分答案的题,你可以先确认某次分段后的可能的最大段的值q,然后尽量往最大段的值方向去分段,这样,在保证了分段后的最大段的值小于等于q,再看所分的段数,如果大于限定的段数,说明不可能最大段的值是q。因为在保证所分段的值不超过q的情况下,无法减少段数使其达到要求,这时应该往大于q的范围上去找。如果小于等于限定的段数,说明可能还有更小的q。因为段数小于要求,可以将某段拆成多段来增大段数,这时可能有更小的q符合要求。而这时为了更快的找到q的值,我们可以使用二分查找的方式去找。对于n个数,最小的q就是每个一段分出n段时,n个数中的最大值,最大的q就是只分出1段时,n个数的和。

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
int check(int max,int *data,int num,int limit_count){
	int current_sum=0,count=0;
	for(int i=0;i<num;i++){
		if(data[i]>max)return 0;
		if(current_sum+data[i]>max){
			count++;
			current_sum=data[i];
		}else current_sum+=data[i];
	}
	count++;
	return count<=limit_count;
}
int main() {
	int N, M, max = 0, sum = 0;
	scanf("%d %d", &N, &M);
	int *data = (int*)malloc(sizeof(int) * N);
	for (int i = 0; i < N; i++) {
		scanf("%d", &data[i]);
		sum += data[i];
		if (data[i] > max)max = data[i];
	}
	int left=max,right=sum;
	while(left<right){
		int mid=(left+right)/2;
		if(check(mid,data,N,M))right=mid;
		else left=mid+1;
	}
	printf("%d",left);
	free(data);
	return 0;
}

书的复制https://www.luogu.com.cn/problem/P1281 这道题的思路和上面的题一模一样,但要注意输出时的条件:行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
int check(int max,int *data,int num,int limit_count){
	int current_sum=0,count=0;
	for(int i=0;i<num;i++){
		if(data[i]>max)return 0;
		if(current_sum+data[i]>max){
			count++;
			current_sum=data[i];
		}else current_sum+=data[i];
	}
	count++;
	return count<=limit_count;
}
int main() {
	int N, M, max = 0, sum = 0;
	scanf("%d %d", &N, &M);
	int *data = (int*)malloc(sizeof(int) * N);
	for (int i = 0; i < N; i++) {
		scanf("%d", &data[i]);
		sum += data[i];
		if (data[i] > max)max = data[i];
	}
	int left=max,right=sum;
	while(left<right){
		int mid=(left+right)/2;
		if(check(mid,data,N,M))right=mid;
		else left=mid+1;
	}
	int result[M][2],current_sum=0,count=0;
	result[0][1]=N,result[M-1][0]=1;
	for(int i=N;i>0;i--){
		if(current_sum+data[i-1]>left){
			result[count++][0]=i+1;
			result[count][1]=i;
			current_sum=data[i-1];
		}else current_sum+=data[i-1];
	}
	for(int i=M-1;i>=0;i--){
		printf("%d %d\n",result[i][0],result[i][1]);
	}
	free(data);
	return 0;
}

切绳子https://www.luogu.com.cn/problem/P1577 这道题比上述的两题都要简单,但值得注意的是,向下取整时一定要使用floor函数,否则将出现部分样例不过的情况。

cpp 复制代码
#include<stdio.h>
#include<math.h>
int check(double current_length,double *data,int num,int limit){
	int count=0;
	for(int i=0;i<num;i++){
		count+=(int)floor(data[i]/current_length);//不加floor会有错误
	}
	return count>=limit;
}
int main() {
	int N,K;
	scanf("%d %d",&N,&K);
	double data[N],left=0.0,right=0.0;
	for(int i=0;i<N;i++){
		scanf("%lf",&data[i]);
		if(data[i]>right)right=data[i];
	}
	while(right-left>1e-6){
		double mid=(left+right)/2.0;
		if(check(mid,data,N,K))left=mid;
		else right=mid;
	}
	printf("%.2lf",left);
	return 0;
}
相关推荐
M78佐菲4 小时前
ARM学习笔记(1)
linux·arm开发·笔记·嵌入式硬件·学习
无敌贵点大王7 小时前
RTThread学习记录11——RT-Thread 设备模型吃透:UART/ADC/PWM/PIN 到底有什么区别?
c语言·stm32·学习·链表
是翎8 小时前
深度长文|2026产品经理AI实践手册
人工智能·深度学习·学习·自然语言处理·数据挖掘
Linux-lucky9 小时前
32-38-Linux学习之旅之MySQL综合
linux·运维·学习·mysql·ubuntu
知识分享小能手10 小时前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
AI职业加油站12 小时前
数据要素价值释放年:大数据治理工程师,站上职业新风口
人工智能·学习·职场和发展·数据分析·职场发展
啄缘之间13 小时前
1.【SVA】什么是SVA?
经验分享·学习·测试用例·verilog·sva
sunoo-22913 小时前
【嵌入式裸机开发Day04】i.MX6ULL 蜂鸣器驱动详解:从引脚地址查找到代码实现全流程
arm开发·单片机·嵌入式硬件·学习·串口·裸机
Purple Coder14 小时前
stm32
学习
边境悍匪14 小时前
蜗牛学苑 Java 智能体学习 Day45|Knife4j+SpringBoot3、书城项目整合 MyBatis 思维导图复盘
java·开发语言·vue.js·学习·spring