[USACO]金发姑娘和N头牛 解题报告

这道题可以转化为Hash+差分序列模型,但我所要说的是在常数上的优化。

考虑转化为差分序列时,我们在其左端点加上Y-X,在右端点的下一位加上Z-Y;并且对于所有牛都是一样的。所以我们交换两个牛的右端点,对答案不会有任何影响。那么我们干脆就把左右端点分开来考虑好了。

有什么好处?

考虑普通的hash,需要先排序再二分≈T(4Nlog(2N)+9N);而根据上述思想,我们完全可以做到排序+线性扫描≈T(2NlogN+7N),可以大大削减常数。

写的时候犯了一些错误:

①把Y当Z使了。。

②没有把右端点+1

③没有处理边界。

④用一个变量表示好多意思的时候,没有分清其在某个时刻的意义到底是什么。

#include<iostream> 
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
int A[20001],B[20001];
char * ptr=(char *)malloc(300000);
inline void in(int &x){
	while(*ptr<'0'||*ptr>'9')++ptr;
	x=0;
	while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';
}
int main(){
	freopen("milktemp.in","r",stdin);freopen("milktemp.out","w",stdout);
	int N,X,Y,Z,i;
	fread(ptr,1,300000,stdin);
	in(N),in(X),in(Y),in(Z);
	for(i=N;i;--i)in(A[i]),in(B[i]),++B[i];
	A[0]=A[N],B[0]=B[N];
	sort(A,A+N),sort(B,B+N);
	int now=X*N,ans=max(now,Z*N),j=0,k;
	Z=Z-Y,Y=Y-X,i=0;
	A[N]=-1,B[N]=-1;
	while(i<N&&j<N){
		k=min(A[i],B[j]);
		while(A[i]==k)now+=Y,++i;
		while(B[j]==k)now+=Z,++j;
		ans=max(ans,now);
	}
	printf("%d",ans);
	return 0;
}

总结:

①寻找题目中的等价关系往往能给我们一些优化。

②处理边界的时候一定要头脑清晰。

你可能感兴趣的:(hash)