二分暑假专题 训练记录 2017-7-29

POJ3258-River Hopscotch

题意:

  给你区间【0,L】给你n个石头,然后去除m个石头  最大化 石头间最小的距离

思路:

  首先0和L 这两个石头是不可以动的   然后用 s 数组记录 整个区间的石头

  然后排序  此时石头的排序就是有序的了  然后二分套模板

  接着check函数才是最关键的好的把

  从0到 n+1-m   总共就有 n+2-m 个石头了 而由于第0个石头不可以动 , 所以从第一个开始动 

  同时判断条件是 s[cur] - s[last] < d 而不是 <=

#include <iostream>
#include <algorithm>

using namespace std;

int l,n,m;
int s[50010];

bool check(int d)
{
    int last = 0; // 1 - n+2-m
    for(int i=1;i < n+2-m ; i++)
    {
        int cur = last + 1;
        while (cur <= n+1 &&s[cur] - s[last] < d )
            cur++;
        if(cur > n+1) return 0;
        last = cur;
    }
    return true;
}

int main()
{
    cin>> l>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>s[i];
    sort(s,s+n+1);
    s[0] = 0,s[n+1] = l;

    int ans = 0;
    int le = 0,ri = l;
    while (le <= ri)
    {
        int mid = (le + ri)/2;
        if( check (mid) ) ans = mid , le = mid+1;
        else ri = mid-1;
    }
    cout << ans <<endl;
    return 0;
}

A

POJ 3104 Drying

题意:

  有n件衣服,每件衣服的含水量为ai单位,每分钟他们能自然脱水1单位,有一个脱水机,每次只能对一件衣服脱水,脱水量为k单位(脱水时不自然风干),问所有衣服全部风干的最小时间是多少?

思路:

  首先能够想到的是可以二分查找全部自然风干的最少时间mid。但这一题不同的是在判断函数中用蛮力法判断mid是否满足条件是会出错。需要特殊处理。

设某次二分出的一个值是mid
1、对于一件ai值小于等于mid的衣服,直接晾干即可;
2、对于一件ai值大于mid值的衣服,最少的用时是用机器一段时间,晾干一段时间,设这两段时间分别是x1和x2,那么有mid=x1+x2,ai<=k*x1+x2,解得x1>=(ai-mid)/(k-1) ,所以对(ai-mid)/(k-1)向上取整就是该件衣服的最少用时。

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
const int mod = 1e9 + 7;
const int maxn = 100000 + 5;
typedef long long LL;
int n,k,s[maxn];

bool check (LL d)//表示在d时间内能做玩
{
    LL sum = 0;
    for(LL i=1;i <= n;i++)
    {
        if(s[i] > d)
        {
            sum +=(s[i] - d + k-2 )/(k-1);//向上取整   +k-2 是为了向上取整
            if(sum > d) return 0;
        }
    }
    return true;
}
int main()
{
    while (~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&s[i]);
        scanf("%d",&k);
        sort(s+1,s+n+1);
        if(k == 1)//特判
        {
            cout<< s[n] <<endl;
            continue;
        }
        LL ans = 0;
        LL le = 0,ri = s[n];
        while (le <= ri)
        {
            LL mid = (le+ri)/2;
            if( check(mid) ) ans = mid,ri = mid-1;
            else le = mid +1;
            //cout<< mid <<endl;
        }
        cout<< ans <<endl;
    }
    return 0;
}

B_注意特判 k为1的情况

POJ 3045 Cow Acrobats(贪心)

题意:

  有N头牛玩叠罗汉游戏,每头牛有一个体重Wi和一个力量Si。 这个游戏对每头牛都有一个危险度等于这头牛上面的牛的体重总和减去他的力量值。

  求所有方案中危险值最大的最小。

思路: 

  按照w+s贪心叠,越大的越在下面。如果最优放置时,相邻两头牛属性分别为weightA,powerA,weightB,powerB,第一头牛在第二头上面,sum为第一头牛上面的牛的体重之和,那么

  第一头牛风险:a=sum - powerA;第二头牛风险:b=sum + weightA - powerB;

  交换两头牛位置之后a‘=sum + weightB - powerA, b‘=sum - powerB,

  所以此时  max(a,a‘) 与 max(b,b‘)比较

  由于是最优放置,所以w2-s1>=w1-s2,即w2+s2>=w1+s1,所以和最大的就该老实的在下面呆着= =!

  此题目有一个WA点 就是危险度可能是负数  所以刚开始初始化的 MAX 必须是比  -1e9 还要小的数.....WA了四次

//C_注意贪心规则
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 50000 + 5;
const int INF = 0x3f3f3f3f;
typedef long long LL;

int n;
struct p{
    int weight,power;
    bool operator < (const p &x)const
    {
        //这里有问题的啊  应该是按照 weight+power 排序 而不是重量大力气小的排
        return weight + power > x.weight + x.power;

    }
}s[maxn];

LL sum = 0;
int main()
{
    while (~scanf ("%d",&n))
    {
        sum = 0;
        for(int i=1;i <= n;i++)
        {
            scanf("%d %d" , &s[i].weight , &s[i].power);
            sum += s[i].weight;
        }
        sort(s+1 , s+1+n);
        LL ans = -INF;
        for(int i=1; i<=n; i++)
        {
            sum =sum- s[i].weight;
            ans = max(ans,sum-s[i].power);
        }
        printf("%lld\n",ans);

    }
    return 0;
}

C_注意贪心规则

POJ1064 Cable master

题意:

  给你n,k   然后给出 n个a[i] 表示每次test 作对的数量   再给n个b[i] 表示每次test 的题数  让你去掉 k 次测验后  平均成绩的最大值

思路:

  看挑战 (最大化平均值)

  有句MMP 不知当讲不当讲

  最后结果的输出   错误 竟然就导致这道题 WA了6次;

  刚开始int (ans*100)    这个没有四舍五入

  改成 printf("%.0lf\n",ans*100); 然后网上找的数据   结果还是WA   我直接准备去 POJ 上交 然后蜜汁过了

  后来发现 VJ上我用的G++

  最后网上搜索了一波 原来是 %f 和 %lf 的原因

  

double num G++提交 C++提交 最安全的方法
输入 scanf(“%lf”, &num); scanf(“%lf”, &num); cin >> num;
输出 printf(“%f”, num); printf(“%lf”, num); cout << num;

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 10000 + 5;
const int INF = 0x3f3f3f3f;

typedef long long LL;
int n,k;
int a[1010],b[1010];
double s[1010];

bool check(double d)
{
    for(int i=0; i<n; i++)
    {
        s[i] = double(1.000*a[i] - 1.000*d*b[i]);
    }
    sort(s,s+n);
    double sum = 0;
    for(int i=0; i<n-k; i++)
    {
        sum += s[n-i-1];
    }
    return sum >= 0;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    std::ios::sync_with_stdio(false);

    while (cin >> n >> k && n+k)
    {
        for(int i=0; i<n; i++)
            cin>>a[i];
        for(int i=0; i<n; i++)
            cin>>b[i];
        double le = 0,ri = 1;
        double ans = 0;
        for(int i=0; i<100; i++)
        {
            double mid = (le + ri)/2.0;
            if(check(mid))
                ans = mid, le = mid;
            else
                ri = mid;
        }
        printf("%.0lf\n",ans*100);
    }
    return 0;
}

D

poj 3685 Matrix

题意:

  Given a N × N matrix A, whose element in the i-th row and j-th column Aij is an number that equals i2 + 100000 × i + j2 - 100000 × j + i × j, you are to find the M-th smallest element in the matrix.   自己能读懂...

思路:

  看别人的题解  发现 如果固定j  就发现函数是个递增函数  所以主函数里的二分是用来判断第M-th数的大小的

  然后check 函数里面的二分 是用来确定小于 m的个数的

  这个题挺好的  晚上再写一遍 加深对二分的理解

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

#define maxn 1e12;
typedef long long LL;
LL k ,n;
LL cal(LL i,LL j)
{
    return i*i + 100000 * i + j*j - 100000 * j + i*j;
}
bool check(LL m)
{
    LL cnt = 0;
    for(int j=1; j<=n; j++)//着相当于固定每一个j 求 <= m的个数
    {
        int le=1,ri = n,ans = 0;
        while (le <= ri)
        {
            int mid = (le + ri)/2;
            if(cal(mid,j) <= m)//如果此时小于等于m 就说明还可以找更大的i 所以左区间缩小
                ans = mid,le = mid+1;
            else
                ri = mid-1;
        }
        cnt += ans;
    }
    return cnt >= k;//如果cnt >= k ,此时就说明这不是第k小  所有让右区间缩小
}
int main ()
{
    std::ios::sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--){
        cin >> n >> k;
        LL le = -100000*n;
        LL ri = n*n+n*n+100000*n+n*n;
        LL ans = 0;
        while (le <= ri)
        {
            LL mid = le+ (ri-le)/2;
            if( check (mid) )
                ans = mid,ri = mid-1;
            else
                le = mid+1;
        }
        cout<< ans <<endl;
    }
    return 0;
}

E 二分套二分

时间: 2024-12-18 17:03:17

二分暑假专题 训练记录 2017-7-29的相关文章

dp暑假专题 训练记录

A 回文串的最小划分 题意:给出长度不超过1000的字符串,把它分割成若干个回文字串,求能分成的最少字串数. #include <iostream> #include <cstdio> #include <string.h> #include <string> using namespace std; const int mod = 1e9 + 7; const int maxn = 1000 + 5; const int INF = 0x3f3f3f3f;

2014暑假ACM训练总结

2014暑假ACM训练总结报告 匆匆之中,一个暑假又过去了,在学校训练的这段日子真的是感觉日子过得好快啊! 时光如箭,日月如梭! 匆忙的学习之中一个暑假就这样结束了,现在就来写一些总结吧,供自己以后阅读和回忆吧! 2014年7月14我们即可1303考完了最后一科模拟电路,也宣告了暑假的到来!本来有刚好两 星期的时间可以回家或是去做其他的事,然后我在学校呆了几天,无聊之余便回家了.在家呆了大概 7天,便正式回校了,准备学校的ACM的训练去了. 先亮一下暑假的训练计划吧! 集训详情: 第一周回顾知识

斜率优化系列——训练记录

斜率优化训练记录 前言 斜率优化一般用于优化dp的转移,借着训练斜率优化的相关问题来提升一些DP思维.选择老学长留下的专题场来练手,由于该场题数较多,以及个人不太愿意长时间进行单一专题训练,因此开此文来记录断续的训练结果和心得. 记录 题一 由一道简单入门题玩具装箱开头,题意和思路比较简单就不讲了. 代码 #include<bits/stdc++.h> #define dd(x) cout<<#x<<" = "<<x<<&qu

【第三组】冲刺会议 2017.7.29

冲刺会议 日期:2017.7.29 开发小组:Geomestry 冲刺经理:程立智 成员: 程立智 李明伦 郑昊 蔡镇泽 温志成 汪涵 成员:程立智 完成工作:实现全局多语言,各种界面大小自适应 ,添加系统推送 所遇问题: 界面难以跟随设置立即更新 下一步工作:实现成就系统,解决大家最后测试出的各种系统bug 成员:李明伦 完成工作:写中英文关卡说明 和 实现关卡初始条件 所遇问题: 个别关卡描述不明确 下一步工作:测试程序在低端笔记本上面是否有运行不良状况 成员:郑昊 完成工作:重构各种界面的

【2017.09.29 星期五 关于c++瞎侃】

c++中最重要的语法特征就是 类 了,通过它,程序员可以自定义自己的数据类型. c++中的类包含 数据成员 也 包含 函数成员. C++语言主要的一个设计目标 就是让程序员自定义的的数据类型向 内置类型一样 好用. 基于此, 标准c++库 实现了丰富的类和函数. 野心很大 [2017.09.29 星期五 关于c++瞎侃]

2017/7/29 SQL PASS台中首发,SQL SERVER 2017 0n Linux ,数据库规划设计

这次我们一次提供两个场次让大家大大的满足 台中的朋友千万不要错过这难得的机会喔! 活动地点:逢甲大学资讯电机馆418教室? 活动时间:7/29 13:00- 17:00? 费用:全天250 活动场次:13:00~15:00? 主题:SQL SERVER 2016 sp1 新功能以及改变与SQL SERVER 2017 0n Linux 讲师:宋明远(Isaac),程品端 (Egg)? 报名网址:https://goo.gl/forms/Xyw0ZliAWLhSzIP72 活动场次:15:00 ~

面试专题训练之“双指针”

一.需要思考的问题包括以下几点: 双指针是什么,什么时候需要用到双指针 通用的模板是什么 实现过程中需要注意的细节有哪些 常见的双指针题型有哪些 二.模板整理 三.专题训练 1.Leetcode283 1 class Solution { 2 public: 3 void moveZeroes(vector<int>& nums) { 4 int n = nums.size(); 5 int j = 0; 6 for (int i = 0; i < n; i++) { 7 if

2017暑假训练记录

目标: 大二上进队参加regional 准备专攻一下计算几何什么的,争取对队伍做些贡献-- 其他题目也会做 8月20日军训前努力提升自己吧 2017.06.11 敲了一些二维的点和直线和多边形的板子 poj1654 Area(多边形面积)

训练记录PART1

11/05 bestcoder #93 C 等价于给出很多环,等概率选择N个点,收益为出现过点的环的环长lcm.不同的环只有 \(\sqrt {26}=6\) 个,用\(f_S\)表示点出现在状态为S的那些环里的选取总数,DP一下即可. bestcoder #93 D 考虑meet in the middle.推一下式子,设左侧选的数和为\(A_{left}t\),两两乘积之和为\(B_{left}\),那么满足\(B_{left}+B_{right}+A_{left}*A_{right}>=0