【SSOJ 4192 做题方案】题解

题目链接

题目

为了期末考取得好成绩,同学们都加倍努力进行复习。

为了考得比其他同学好,小泽决定每一科都认真地多做1道题目,以提高对知识点的理解和熟悉程度!

已知期末要考4门课,分别是《C++编程》、《算法入门》、《数据结构》、《搜索算法》,每一门课老师都准备了n道复习题,第一道题的耗时分别是\(a_1、b_1、c_1、d_1\),第二道题的耗时分别是\(a_2、b_2、c_2、d_2\)……

小泽打算花恰好m分钟(充分利用时间)来完成4道题,每个科目各一道,请问有多少种选择方案?

思路

先对 \(a\)\(b\) 的和作个排序,再对 \(c\)\(d\) 的和作个排序,然后双指针跑一遍统计答案。

总结

这道题我一开始想的是把两个和做出来后作个二分,后来发现答案符合单调性,双指针即可。

对于要对数列多次二分的题目,一般都可以用双指针优化。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 510
int n, m, i, j, k; 
int a[N], b[N], c[N], d[N], x[N*N], y[N*N]; 
int l, r, ans; 

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	n=read(); m=read(); 
	for(i=1; i<=n; ++i) scanf("%lld%lld%lld%lld", &a[i], &b[i], &c[i], &d[i]); 
	for(i=1; i<=n; ++i) for(j=1; j<=n; ++j) x[(i-1)*n+j]=a[i]+b[j]; 
	for(i=1; i<=n; ++i) for(j=1; j<=n; ++j) y[(i-1)*n+j]=c[i]+d[j]; 
	sort(x+1, x+n*n+1); 
	sort(y+1, y+n*n+1); 
	for(l=1, r=n*n; l<=n*n; ++l)
	{
		while(r&&x[l]+y[r]>m) --r; 
		ans+=r; 
	}
	printf("%lld\n", ans); 
	return 0; 
}

posted @ 2022-01-12 21:11  zhangtingxi  阅读(41)  评论(0编辑  收藏  举报