zoukankan      html  css  js  c++  java
  • Codeforces Round #352 (Div. 2)

    模拟 A - Summer Camp

    #include <bits/stdc++.h>
    
    int a[1100];
    int b[100];
    int len;
    
    void init() {
        int i = 1, tot = 1;
        while (tot <= 1010) {
            int t = i, c = 0;
            while (t) {
                b[c++] = t % 10;
                t /= 10;
            }
            for (int i=c-1; i>=0; --i) {
                a[tot++] = b[i];
            }
            i++;
        }
    }
    
    int main() {
        init ();
        int n; scanf ("%d", &n);
        printf ("%d", a[n]);
        return 0;
    }
    

    构造 B - Different is Good

    题意:问最少改变多少个字母使得该字符串的所有子串不相同

    分析:子串有长度为1的,所以如果字符串长度大于26一定不可行,否则就把相同的字母用没出现的字母替换.

    #include <bits/stdc++.h>
    
    const int N = 1e5 + 5;
    char str[N];
    int vis[30];
    
    int main() {
        int n; scanf ("%d%s", &n, str);
        if (n > 26) {
            puts ("-1");
        } else {
            int ans = 0;
            for (int i=0; i<n; ++i) {
                if (vis[str[i]-'a']) {
                    ans++;
                } else {
                    vis[str[i]-'a'] = true;
                }
            }
            printf ("%d
    ", ans);
        }
        return 0;
    }
    

    几何+贪心 C - Recycling Bottles

    题意:A和B捡罐头,每次只能捡一个然后到垃圾桶去,再从垃圾桶出发去捡,问捡完所有罐头所需的最少总路程

    分析:除从A或B出发第一次捡罐头的距离不确定外,其他的都可以看成sum (dis (T, p[i]) *2),所以只需要 min (-dis (T, p[i]) + dis (A, p[i])).因为A和B捡罐头是独立的,只要A和B都捡一个罐头使得差值最小,重复时特判下就行了.更一般的做法是A任意选择一个罐头,B选择除A选的外里最小差值的那一个,可以预处理出前缀最小和后缀最小.

    #include <bits/stdc++.h>
    
    const int N = 1e5 + 5;
    const double INF = 1e18 + 5;
    const double EPS = 1e-8;
    struct Point {
        double x, y;
        Point() {}
        Point(double x, double y) {
            this->x = x;
            this->y = y;
        }
    }point[N];
    Point A, B, O;
    double dis[N];
    double sum;
    double pre[N], suff[N];
    double add[N];
    int n;
    
    Point read_point() {
        double x, y; scanf ("%lf%lf", &x, &y);
        return Point (x, y);
    }
    
    double squ(double x) {
        return x * x;
    }
    
    double calc_dis(Point a, Point b) {
        return sqrt (squ (a.x - b.x) + squ (a.y - b.y));
    }
    
    int main() {
        A = read_point ();
        B = read_point ();
        O = read_point ();
        scanf ("%d", &n);
        for (int i=1; i<=n; ++i) {
            point[i] = read_point ();
            dis[i] = calc_dis (point[i], O);
            pre[i] = suff[i] = -dis[i] + calc_dis (point[i], B);
            add[i] = -dis[i] + calc_dis (point[i], A);
            sum += dis[i] * 2;
        }
        pre[0] = suff[n+1] = INF;
        for (int i=1; i<=n; ++i) {
            pre[i] = std::min (pre[i], pre[i-1]);
        }
        for (int i=n; i>=1; --i) {
            suff[i] = std::min (suff[i], suff[i+1]);
        }
        double ans = sum + suff[1];  //just B
        for (int i=1; i<=n; ++i) {
            ans = std::min (ans, sum + std::min (0.0, std::min (pre[i-1], suff[i+1])) + add[i]);
        }
        printf ("%.12f
    ", ans);
        return 0;
    }
    

    二分 D - Robin Hood

    题意:n个人,k次操作,每次把最大的数分1到最小的数,问k次后最大值和最小值的差

    分析:二分最小值和最大值,思想是求出min(max) 刚好使得小于它的到它的操作正好是k.处理好二分的边界,因为二分时是尽量使得最小值大,最大值小.

    #include <bits/stdc++.h>
    
    typedef long long ll;
    const int N = 5e5 + 5;
    int a[N];
    int n, k;
    
    bool check(int val, int op) {
        ll need = 0;
        for (int i=0; i<n; ++i) {
            if (op == 1) {
                if (a[i] <= val) {
                    need += val - a[i];
                } else {
                    break;
                }
            } else if (op == 2 && a[i] >= val) {
                need += a[i] - val;
            }
        }
        return need <= k;
    }
    
    int main() {
        scanf ("%d%d", &n, &k);
        ll sum = 0;
        for (int i=0; i<n; ++i) {
            scanf ("%d", a+i);
            sum += a[i];
        }
        std::sort (a, a+n);
        int ansl = -1, ansr = 1e9;
        int left = a[0], right = sum / n;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (check (mid, 1)) {
                ansl = mid;
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        left = sum / n;
        if (sum % n) {
            left++;
        }
        right = a[n-1];
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (check (mid, 2)) {
                ansr = mid;
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        printf ("%d
    ", ansr - ansl);
        return 0;
    }
    

      

  • 相关阅读:
    python实现从生成器中取固定角标的元素
    python-高阶函数
    git学习手册
    python批量进行文件修改操作
    python第一站
    LoadRunner,一个简单的例子
    python3中urllib2的问题
    gitlab 随笔
    sed 删除文本
    sed 修改文本
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5491122.html
Copyright © 2011-2022 走看看