算法竞赛进阶指南学习day4

CH0304 / P4552

知识点:差分

关于差分:

差分数组存储了原数组相邻元素的差,方便进行区间修改,若对差分数组a[n]中区间[l,r]进行加x操作,那么a[l]+x,a[r+1]+1,就可以完成区间修改

思路:题目是对区间进行操作,所以很容易想到用差分,于是题目中的区间修改转变成修改2个位置,题目要把所有元素变一样,翻译一下就是让差分数组除了最后一个全是0,差分数组中有正有负,那么全部正数与负数互相抵消之后就得到一个最后一个是数,其他全是0的差分数组,这就代表原始数组只有最后一个,处理最后一个有两种方法:1、只处理最后一个,2、改变其他的所有值第二问解出

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int main(){
	long long n;
	long long a[100010]={};
	long long b[100010]={};
	cin>>n;
	for(int i=0;i<n;i++){
	 	cin>>a[i];
	}
	for(int i=1;i<n;i++){
		b[i-1]=a[i-1]-a[i];
	}
	long long x=0,y=0;
	for(int i=0;i<n;i++){
		if(b[i]>0){
			x+=b[i];
		}else{
			y-=b[i];
		}
	}
	cout<<max(x,y);
	cout<<endl<<abs(x-y)+1;
	return 0;
}

关于二分:

进行缩小范围时,若范围出现负值,用右移操作而不直接除以2,区别在于,右移是向下取整,/2是向0取整

int main(){
	cout<<"1:"<<(-3>>1)<<endl;
	cout<<"2:"<<(-3/2)<<endl; 
	return 0;
}
/*
输出: 
1:-2
2:-1

--------------------------------
Process exited after 0.01619 seconds with return value 0
请按任意键继续. . .

*/

poj2018

思路:二分答案,前缀和求区间和

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;double a[100001],b[100001],sum[100001];
double min(double a,double b){
	return (a<b? a:b);
}
int main(){
	
	int n,L;
	cin>>n>>L;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	} 
	double c=1e-5;
	double r=1000000;
	double l=-1000000;
	while(r-l>c){
		double mid=(r+l)/2;
		for(int i=1;i<=n;i++){
			b[i]=a[i]-mid;
		} 
		for(int i=1;i<=n;i++){
			sum[i]=sum[i-1]+b[i];
			
		} 
		double ans=-1e9;
		double minn=1e10;
		for(int i=L;i<=n;i++){
			minn=min(minn,sum[i-L]);
			ans=max(ans,sum[i]-minn);
		} 
		if(ans>=0){
			l=mid;
		}
		else{
			r=mid;
		}
	}
	cout<<int(r*1000);
	
	return 0;
}

关于离散化

当数据范围很大,但个数右很少的时候,或者存在大量重复的时候,可以用一个相对规模小很多的数组来与大范围的建立映射关系

CH0501

思路:中位数

#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
int a[1000000];
int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	sort(a,a+n);
	int mid=a[(n+1)/2];//规避奇偶
	int ans=0;
	for(int i=0;i<n;i++){
		ans+=abs(mid-a[i]);
	} 
	cout<<ans;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值