5044:
简单模拟即可
5045:
三角形数:n(n+1)/2,求询问的数是否是俩个三角形数的和
我们先用f[]初始化所有三角形数的和,f[i]=(i+1)i/2;
分析:从暴力优化到双指针
暴力:
for(int i=1;i<=n;i++)
for(int j=n;j>=1;j--0
if(f[i]+f[j]==k) get;
但是由于是f是有序的:
当f[i]+f[j]<k时,当j变小,f[i]+f[j]一定会小于k,故可以停止j的循环,直接i++;
for(int i=1;i<=n;i++)
for(int j=n;j>=1;j--)
if(f[i] + f[j] < k) break;
else if(a[i] + b[j] == k) get;
当f[i]+f[j+1]>k,那么f[i+1]+f[j+1]肯定也大于k
所有i在进入下一次循环时,i+1不用回到m重新递减,保持不变即可
int j = m ;
for(int i = 1; i <= n; i++){
while(j >= 0){
if(f[i] + f[j] < k){
break;
}
else if(f[i] + f[j] == k){
get
return 0;
}
else{
j -= 1;
}
}
}
那我们换种写法写法,就变成了双指针:
真是个好证明,不然做题不知道为什么是对的
int i=1,j=n;
while(i<=n&&j>=1)
{
if(f[i]+f[j]==k)get;
else if(f[i]+f[j]>k)j--;
else i++;
}
5046:
//注意到本题的智力是只能递增,因此我们对r进行排序
//状态表示:只选前i种药且选了第i种药
//状态转移,f[i]=f[l]+f[l+1]+…+f[r-1]
//由于每次f都是在右边更新,前面的f不会变,因此可以用前缀和优化