每日总结7/20

9.00-11.00

        浏览式大概了解学习mvc,css

11.00-

        vj题

最长递增子序列_F

 我的百度翻译告诉我题意是,找到包含n的最长连续递增子序列,我都被搞自闭了我说啊这也太动态了吧想不通怎么写,好久之后才知道正确题意,简单多了

这个题可以用动态规划来写,dp【i】存储以a【i】结尾的递增子序列的长度

ans=max(dp1....n);

原理嘞我感觉我讲不清,直接看例子吧

n=6

  a【6】        2        1        3        4        6        5

dp【6】        1        1        2        3        4        4 

每次判断a[i]和a[j]的大小,如果a[i]>a[j],获取dp[i]和dp[j]+1中的较大值

void Dp()
{
    for(int i=0;i<n;i++)
    	dp[i]=1;//以a[i]结尾的递增子序列长度初始值为1 
	for(int i=0;i<n;i++)
        for(int j=0;j<i;j++){
            if(a[j]<a[i])
                dp[i]=max(dp[i],dp[j]+1);
        }
}

时间复杂度是O(n^2),提交时间超限了

一开始看到限制条件1≤N≤100,000我就应该想到

用一个b【ans】数组存储序列,数组的长度就是该题的解,另ans=1(序列初始值就是1)

如果b【ans】>a【i】,将a【i】放到b序列的尾部

否则,查找到b【ans】中第一个大于或者等于a【i】的数,将a【i】替换到那个位置(ans没变)

(虽然最后b序列里不一定是最长递增子序列,但是长度是正确的)

优化算法,查找到b【ans】中第一个大于或者等于a【i】的数时,可以用二分查找降低时间复杂度

可以直接调用二分查找函数,使用algorithm头文件

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

算法过程在遇到的问题:ans++ 和 ++ans

我之前用的ans++,样例都过不去,出来的一个答案,比n还大,一想就能想到是计数记错了,将ans++改为了++ans就过了

对于ans++的实现是:

int temp;
temp = ans;
ans = ans+1;
return ans;

 (关于这个涉及到了一个寄存器的概念)

对于++ans的实现是

ans = ans+1;
return ans;

投票_G

不难看出这道题需要用二分来写,思路是慢慢想出来的捏

我一开始想到的答案实际上实现的是,每一张纸条上的值都相等,算的一个平均值,思路完全错了

首先如果n==m,答案就是所有网站中票数最多的那个,另它为mmax

上界 r=mmax (模拟的n==m的时候)

下界 l=0  (模拟的所有网站都没有票数的时候)

ac核心代码

bool check(int x)
{
    int cnt=0;//代表需要的纸条数
    for(int i=0;i<n;i++){
        cnt += ceil(a[i]*1.0/x);
        /*ceil()函数用来向上取最接近的整数值
        因为int型不能整除的话,是直接截取掉小数点后面的数
		但是实际上,没有达到也算一张小纸条条的嘞~ 
		*/ 
        if(cnt>m)
            return false;
    }
    return true;
}

ceil()向上舍入最接近的整数值

floor()向下舍入最接近的整数值

round()对浮点数进行四舍五入

搭积木_H

 分析可知,如果n个人2、4、6、8、10得搭积木,m个人3、6、9、12得搭积木

仅当搭的积木为6的倍数的时候,可能会搭一样的积木

另如果不与只能搭用高度为3的人比较,n个人能搭的最高积木为ans2=n*2

另如果不与只能搭用高度为2的人比较,m个人能搭的最高积木为ans3=n*3

如果ans2,ans3的最小值都大于6,说明肯定会有搭重复积木块的人,因为要求最少能搭的堆堆,所以可以判断ans2、ans3这两个数中,小的那个数去搭不是6的倍数的积木

核心代码

    int ans2=2*n;
    int ans3=3*m;
    for(int i=6;i<=min(ans2,ans3);i+=6){
        if(ans2<=ans3){
            ans2+=2;
        }
        else ans3+=3;
    }
    cout<<max(ans2,ans3)<<endl;

切鼠条_J

这个题就很简单一个二分,重点是精度问题

因为输入的是两位小数,所以在将鼠条们存入数组的时候,可以都先乘以100,方便计算 

我不晓得为什么样例明明都过了还一直WA,无语

代码先放这吧

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e4+10;
int n,k;
double a[N],mmax=0;

bool check(int x)
{
    int cnt=0;
    for(int i=0;i<n;i++){
        cnt+=a[i]/x;
    }
    if(cnt>=k)
        return true;
    else
        return false;
}

int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++){
    	double temp;
        scanf("%lf",&temp);
        a[i]=temp*100;
        mmax=max(mmax,a[i]);
    }
    int l=0,r=mmax,mid=(r+l)/2;
    while(l<=r){
        if(check(mid))
            l=mid+1;
        else
            r=mid-1;
        mid=(r+l)/2;
    }
    printf("%.2lf",mid/100.0);
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值