zoukankan      html  css  js  c++  java
  • 二分。三分

    https://vjudge.net/contest/271273#problem/A

    哎,后面有个四舍五入的问题。

    if( (int) (right * 1000) % 10 >= 5)
    right -= 0.005;
    printf("%.2f
    ", right);

    .2f是默认四舍五入的,上面一段代码是取消四舍五入。

    
    

    https://vjudge.net/contest/271273#problem/M

    https://vjudge.net/contest/271273#problem/J

    三分

    https://vjudge.net/contest/271273#problem/N

    数学题,不会

    https://cn.vjudge.net/contest/260332#status/xiayuyang/A

    二分尺取

    一般如果是那种求精度的,直接lb.ub = mid; ub - lb < 1ex;或者用for循环x次(一般为100,2的一百次方够了)

    如果是那种求 lb < ub,这种要lb + 1, ub - 1;

    最小值最大化的二分区间是右闭左开(L,R],每次二分的中心为M=(L+R+1)/2;最大值最小化的二分区间是左闭右开,[L,R),每次二分的中心为M=(L+R)/2。

    因为。。。。

    二分时间复杂度nlogn;

    二分法:适用于单调函数,单调增或单调减

    三分法:适用于单峰凸性函数,如二次函数,或者是要求两个点

    http://www.cnblogs.com/xiaowuga/p/8609943.html

     poj 3273  Monthly Expense  最小化最大值

    题目意思:

    给出John在N个月中每个月的花费,John想将N个月分成M个组。
    每组的月份是连续的,同一组的花费被相加起来,求所有分组情况中最高花费的最低值。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxm = 1e5 + 5;
    int a[maxm];
    int n, m;
    
    bool fun(int x, int val) {
    for(int i = 0; i < n; i++) {
    int res = a[i];
    if(res <= x) {
        while(res <= x) {
            i++;
            res += a[i];
            val--;
            if(i >= n) break;
        }
        val++;
        i--;
    //    printf("vsdnvs
    ");
    }
    else {
        return false;
    }
    }
    if(val <= 0) return true;
    else return false;
    }
    
    int main() {
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    int l = 0, r = 1e9, mid;
    while(l <= r) {
    mid = (l + r) / 2;
    if(fun(mid, n - m)) {
        r = mid - 1;
    }
    else {
        l = mid + 1;
    }
    }
    if(fun(l, n - m)) printf("%d
    ", l);
    else if(fun(r, n - m)) printf("%d
    ", r);
    //printf("%d
    ", fun(500, n - m));
    
    return 0;
    }

    River Hopscotch  最大化最小值

    牛过河,有很多石头,起点为1,终点为n,移去m快石头,求之后的最小值。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    const int maxm  = 50010;
    int dis, n, m, a[maxm];
    
    bool fun(int x, int val) {
    for(int i = 1; i <= n + 1; i++) {
        int res = a[i - 1];
        if(a[i] - res < x) {
            while(a[i] - res < x) {
                i++;
                val--;
                if(i > n + 1) break;
            }
        }
    }
    if(val < 0) return false;
    else return true;
    }
    
    int main() {
    scanf("%d%d%d", &dis, &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    a[n + 1] = dis;
    sort(a, a + 2 + n);
    int l = 0, r = 1e9, mid;
    while(l <= r) {
        mid = (l + r + 1) / 2;
        if(fun(mid, m)) {
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }
    }
    if(fun(r, m)) printf("%d
    ", r);
    else if(fun(l, m)) printf("%d
    ", l);
    
    
    return 0;
    }

    Flyer

     HDU - 4768 想法二分,一些人给 学校所有人发传单,a,b,c,发给a + k* c;k大于等于0,序号不小于c,求拿到奇数的那个人。

    n个社团派发传单,有a,b,c三个参数,派发的规则是,派发给序号为a,a+c....a+k*c,序号要求是小于等于b
    这其中,有一个学生只收到了奇数传单,要求找出这个学生的编号与得到的传单数目

    思路:如果使用异或运算,也还是比较简单的,但是这样的话所花费的时间就比较长,正确的做法是使用二分
    使用二分来划分区间,由于是每个社团得到的序列都是等差数列,所以我们很容易能得到区间派发的传单数
    如果是奇数,那么所求的人肯定在左区间,否则在右区间,这样二分下去找到答案
    https://blog.csdn.net/libin56842/article/details/25741317

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    
    typedef long long ll;
    const int maxm = 2e4 + 5;
    
    ll n, A, B, C, a[maxm], b[maxm], c[maxm];
    
    bool solve(ll d) {
    ll num = 0;
    for(int i = 0; i < n; i++) {
        if(d >= a[i]) {
            ll x = min(d, b[i]);
            num += (x - a[i]) / c[i] + 1;
        }
    }
    return num % 2;
    }
    
    ll  check(ll d) {
    ll num = 0;
    for(int i = 0; i < n; i++) {
        if(d >= a[i] && d <= b[i]) {
            if( (d - a[i]) % c[i] == 0 ) num++;
        }
    }
    return num;
    }
    
    int main() {
    
    while(~scanf("%lld", &n)) {
        for(int i = 0; i < n; i++) {
            scanf("%lld%lld%lld", &a[i], &b[i], &c[i]);
        }
    
        ll lb = -1, ub = 1ll << 32, ans = 0;
        while(lb <= ub) {
            ll mid =  (ub + lb) / 2;
            if(solve(mid)) {
                ub = mid - 1;
                ans = mid;
            }
            else lb = mid + 1;
        }
        if(check(ans) % 2) printf("%lld %lld
    ", ans, check(ans));
        else printf("DC Qiang is unhappy.
    ");
    
    }
    return 0;
    }

    https://vjudge.net/contest/271273#problem/J

    看一下代码 三分

    A Star not a Tree? POJ - 2420

    和poj1379差不多 
    很多个点,求一个点到所有点的距离之和最小。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    typedef pair<double, double> pii;
    pii p[105];
    int n;
    
    double sum(double x, double y) {
    double num = 0;
    for(int i = 0; i < n; i++) {
        num += sqrt( (x - p[i].first) * (x - p[i].first) + (y - p[i].second) * (y - p[i].second) );
    
    }
    return num;
    }
    
    double check(double d) {
    double lb = 0, ub = 10001;
    for(int i = 0; i < 100; i++) {
        double midy = (lb + ub) / 2.0;
        double midmidy = (midy + ub) / 2.0;
        if(sum(d, midy) < sum(d, midmidy)) {
            ub = midmidy;
        }
        else lb = midy;
    }
    return min(sum(d, ub), sum(d, lb));
    }
    
    int main() {
    
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%lf%lf", &p[i].first, &p[i].second);
    
    }
    double lb = 0, ub = 10001;
    for(int i = 0; i < 100; i++) {
    
        double midx = (lb + ub) / 2.0;
        double midmidx = (midx + ub) / 2.0;
        if(check(midx) < check(midmidx)) {
            ub = midmidx;
        }
        else lb = midx;
    }
    printf("%.0f
    ", min(check(lb), check(ub)));
    
    return 0;
    }

    UmBasketella

     POJ - 3737 

    已知圆锥面积求体积,高

    公式:圆锥面积=PI * r * r + PI * r * l (l为母线长度)

       l * l = h * h + r * r.

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const double PI = acos(-1.0), eps = 1e-6;
    double s;
    double cal(double r)
    {
        double R = s/(PI*r) - r;
        double h = sqrt(R*R - r*r);
        return h*PI*r*r/3;
    }
    int main()
    {
        while(scanf("%lf", &s) != EOF)
        {
            double left = 0, right = sqrt(s/(2*PI)), v;
            while(right - left > eps)
            {
                double middle = (left + right) / 2;
                double middleright = (middle + right) / 2;
                double v1 = cal(middle);
                double v2 = cal(middleright);
                if(v1 >= v2)
                {
                    right = middleright;
                    v = v1;
                }
                else
                {
                    left = middle;
                    v = v2;
                }
            }
            double r = right;
            double H = sqrt((s/(PI*r) - r)* (s/(PI*r) - r) - r*r);
            printf("%.2f
    %.2f
    %.2f
    ", v, H, r);
        }
        return 0;
    }

    Light Bulb

     数学题(主要是退公式) 精度尽量改小点。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int t;
    double D,H,h;
    double fun2(double x) {
        return D - x + H - (H - h) * D / x;
    }
    
    double fun(double l, double r) {
        double mid, midmid, res;
        while(r - l >= 1e-9) {
            mid =(l + r) / 2;
            midmid = (mid + r) / 2;
            double a = fun2(mid);
            double b = fun2(midmid);
            if(a < b) {
                l = mid;
                res = fun2(mid);
            }
            else {
                r = midmid;
                res = fun2(midmid);
            }
        }
        return res;
    }
    int main() {
        scanf("%d", &t);
        while(t--) {
            scanf("%lf%lf%lf", &H, &h, &D);
            printf("%.3f
    ", fun((H - h) * D / H, D));
        }
        return 0;
    }

     https://vjudge.net/contest/283149#problem/A专题

  • 相关阅读:
    异常 中断 陷阱
    关于delete字符串 需不需要加 [ ]
    关于联合体输出的问题(是否小端模式)
    String reorder
    数据库 ---5 索引 创建用户及授权 数据备份
    数据库 --- 4 多表查询 ,Navicat工具 , pymysql模块
    数据库 --- 3 行(记录)操作 单表查询
    数据库 --- 2 库 ,表
    数据库 --- 1 初始 数据库
    并发 --- 5 线程的其他方法 线程队列 线程池 协程
  • 原文地址:https://www.cnblogs.com/downrainsun/p/9986634.html
Copyright © 2011-2022 走看看