Codeforces Round #339 (Div. 1) ABC

A Peter and Snow Blower

多边形与中心最远距离作大圆,最近距离作小圆,答案是大圆面积减去小圆面积。检查下中心是否在多边形内,如果在最近距离就是0。注意最远距离只会出现在点上,而最近距离可能出现在点上和边上。这题没什么意思,就是贴下计算几何模板。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    class Point {
        double x;
        double y;

        Point(double x, double y) {
            this.x = x;
            this.y = y;
        }

        double Cross(Point point) {
            return x * point.y - y * point.x;
        }

        double Dot(Point point) {
            return x * point.x + y * point.y;
        }

        double Distance(Point point) {
            return Math.sqrt((x - point.x) * (x - point.x) + (y - point.y)
                    * (y - point.y));
        }

        Point Sub(Point point) {
            return new Point(x - point.x, y - point.y);
        }
    }

    int n;
    Point pt;
    Point[] pts;

    void Solve() {

        FastScanner scan = new FastScanner();
        n = scan.nextInt();

        int px = scan.nextInt();
        int py = scan.nextInt();
        pt = new Point(px, py);
        pts = new Point[n + 1];

        for (int i = 0; i < n; i++) {
            int x = scan.nextInt();
            int y = scan.nextInt();
            pts[i] = new Point(x, y);
        }
        pts[n] = pts[0];

        boolean positive = false;
        boolean negative = false;
        for (int i = 0; i < n; i++) {
            Point vec = pts[i + 1].Sub(pts[i]);
            double X = vec.Cross(pt.Sub(pts[i]));
            if (X < 0) {
                negative = true;
            }
            if (X > 0) {
                positive = true;
            }
        }

        double maxDist = 0;
        double minDist = Double.MAX_VALUE;
        if (!(positive && negative)) {
            minDist = 0;
        }
        for (int i = 0; i < n; i++) {
            double p2p = pt.Distance(pts[i]);
            maxDist = Math.max(maxDist, p2p);
            minDist = Math.min(minDist, p2p);
            double a = pts[i].Distance(pts[i + 1]);
            double b = pts[i].Distance(pt);
            double c = pts[i + 1].Distance(pt);
            double p = (a + b + c) / 2;
            double S = Math.sqrt(p * (p - a) * (p - b) * (p - c));
            double p2l = S * 2 / a;
            if (pt.Sub(pts[i]).Dot(pts[i + 1].Sub(pts[i]))
                    * pt.Sub(pts[i + 1]).Dot(pts[i].Sub(pts[i + 1])) >= 0)
                minDist = Math.min(minDist, p2l);
        }
        double ans = Math.PI * (maxDist * maxDist - minDist * minDist);
        System.out.print(ans);
    }

    public static void main(String[] args) {
        new Main().Solve();
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(String s) {
            try {
                br = new BufferedReader(new FileReader(s));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String nextToken() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public boolean EOF() {
            if (st != null && st.hasMoreTokens()) {
                return false;
            } else {
                String line = null;
                try {
                    line = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (line == null)
                    return true;
                st = new StringTokenizer(line);
                return false;
            }
        }

        int nextInt() {
            return Integer.parseInt(nextToken());
        }

        long nextLong() {
            return Long.parseLong(nextToken());
        }

        double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}

B Skills

首先排序,然后枚举加满的技能的数量。对于每次枚举,用二分计算能把最低级的技能加到多少,取一个总分的最大值即可。写的时候要细心,不然容易出bug。
另外,原本以为加满技能的数量->总分是一个凸函数,写了个三分套二分一直WA。后来把三分作了些修改,当区间小到一定程度时改为枚举过掉了(实际上姿势还是不对的)。。因为后来事实证明那不一定是凸函数。写完以后还有个发现,自变量离散(因为只能取整数)和连续的三分是有区别的。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    class Node implements Comparable<Node> {
        long val;
        int id;

        @Override
        public int compareTo(Node o) {
            // TODO Auto-generated method stub
            if (val < o.val) {
                return -1;
            } else if (val == o.val) {
                return 0;
            } else {
                return 1;
            }
        }
    }

    int n;
    long A, cf, cm;
    long m;
    Node[] a;
    long[] rsum;
    long[] lsum;

    long BinerySearch(int l, int r, long val) {
        int mid;
        int pos = 0;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (lsum[mid] <= val) {
                pos = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        val -= lsum[pos];
        long res = a[pos].val + val / (pos + 1);
        res = Math.min(res, A);
        return res;
    }

    void Solve() {
        FastScanner scan = new FastScanner();
        n = scan.nextInt();
        A = scan.nextLong();
        cf = scan.nextLong();
        cm = scan.nextLong();
        m = scan.nextLong();
        a = new Node[n + 1];
        lsum = new long[n + 1];
        rsum = new long[n + 1];

        for (int i = 0; i < n; i++) {
            a[i] = new Node();
            a[i].val = scan.nextLong();
            a[i].id = i;
        }

        Arrays.sort(a, 0, n);

        for (int i = 1; i < n; i++) {
            lsum[i] = lsum[i - 1] + (a[i].val - a[i - 1].val) * i;
        }
        lsum[n] = Long.MAX_VALUE;

        int leftMost = 0;
        for (int i = n - 1; i >= 0; i--) {
            rsum[i] = rsum[i + 1] + (A - a[i].val);
            if (rsum[i] > m) {
                leftMost = i + 1;
                break;
            }
        }

        long maxP = 0;
        int left = leftMost;
        long MIN = A;
        for (int i = n; i >= leftMost; i--) {
            long mm = m - rsum[i];
            long tmp = BinerySearch(0, i - 1, mm);

            long power = tmp * cm + (n - i) * cf;
            if (tmp == A) {
                power = A * cm + n * cf;
            }
            if (power >= maxP) {
                maxP = power;
                left = i;
                MIN = tmp;
            }
        }

        long[] ans = new long[n + 1];
        for (int i = 0; i < n; i++) {
            int id = a[i].id;
            ans[id] = a[i].val;
            if (i >= left) {
                ans[id] = A;
            } else if (ans[id] < MIN) {
                ans[id] = MIN;
            }
        }

        PrintWriter out = new PrintWriter(System.out);
        out.println(maxP);
        for (int i = 0; i < n; i++) {
            out.print(ans[i] + " ");
        }
        out.println();
        out.flush();
    }

    public static void main(String[] args) {
        new Main().Solve();
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(String s) {
            try {
                br = new BufferedReader(new FileReader(s));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String nextToken() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public boolean EOF() {
            if (st != null && st.hasMoreTokens()) {
                return false;
            } else {
                String line = null;
                try {
                    line = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (line == null)
                    return true;
                st = new StringTokenizer(line);
                return false;
            }
        }

        int nextInt() {
            return Integer.parseInt(nextToken());
        }

        long nextLong() {
            return Long.parseLong(nextToken());
        }

        double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}

C Necklace

这题我写的比较繁琐。首先找规律可以发现如果出现2个及以上奇数,则无法形成回文。否则,答案是这些数的GCD。构造的时候,可以递归去拼接(拆成gcd段,交替连接当前字符和其他字符)。这个过程比较复杂,详见代码。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
    int n;
    int[] a;
    char[] chars;

    int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    StringBuilder Construct(int[] arr, int s) {
        if (s > n) {
            return new StringBuilder("");
        }

        StringBuilder res = new StringBuilder();
        int odd = 0;
        for (int i = s; i <= n; i++) {
            if (arr[i] % 2 == 1) {
                odd++;
                // swap
                int tmp = arr[i];
                arr[i] = arr[s];
                arr[s] = tmp;
                char tmp2 = chars[i];
                chars[i] = chars[s];
                chars[s] = tmp2;
            }
        }
        if (odd > 1 || s == n) {
            for (int i = s; i <= n; i++) {
                for (int j = 1; j <= arr[i]; j++) {
                    res.append(chars[i]);
                }
            }
            return res;
        }

        int GCD = arr[s];

        for (int i = s + 1; i <= n; i++) {

            GCD = gcd(GCD, arr[i]);
        }

        int end = arr[s] / GCD;
        int[] newArr = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            newArr[i] = arr[i] / GCD;
        }

        StringBuilder sbS = new StringBuilder();
        for (int i = 1; i <= end; i++) {
            sbS.append(chars[s]);
        }
        StringBuilder others = Construct(newArr, s + 1);

        String left = others.toString();
        String right = others.reverse().toString();

        if (arr[s] % 2 == 0) {
            res.append(right);
            for (int t = 1; t <= GCD / 2; t++) {
                res.append(sbS);
                res.append(sbS);
                if (t != GCD / 2) {
                    res.append(left);
                    res.append(right);
                } else {
                    res.append(left);
                }

            }
        } else {
            left = left.substring(0, left.length() / 2);
            right = new StringBuilder(left).reverse().toString();
            res.append(right);
            for (int t = 1; t <= GCD; t++) {
                res.append(sbS);
                if (t != GCD) {
                    res.append(left);
                    res.append(right);
                } else {
                    res.append(left);
                }
            }
        }
        return res;
    }

    void Solve() {
        FastScanner scan = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        n = scan.nextInt();
        a = new int[n + 1];
        chars = new char[n + 1];
        chars[1] = 'a';
        for (int i = 2; i <= n; i++) {
            chars[i] = (char) (chars[i - 1] + 1);
        }
        int odd = 0;
        for (int i = 1; i <= n; i++) {
            a[i] = scan.nextInt();
            if (a[i] % 2 == 1) {
                odd++;
            }
        }

        int GCD = a[1];
        for (int i = 2; i <= n; i++) {
            GCD = gcd(GCD, a[i]);
        }

        StringBuilder sb = new StringBuilder();
        if (odd > 1) {
            out.println(0);
        } else {
            out.println(GCD);
        }
        sb = Construct(a, 1);
        out.println(sb);
        out.flush();
    }

    public static void main(String[] args) {
        new Main().Solve();
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(String s) {
            try {
                br = new BufferedReader(new FileReader(s));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String nextToken() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        public boolean EOF() {
            if (st != null && st.hasMoreTokens()) {
                return false;
            } else {
                String line = null;
                try {
                    line = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (line == null)
                    return true;
                st = new StringTokenizer(line);
                return false;
            }
        }

        int nextInt() {
            return Integer.parseInt(nextToken());
        }

        long nextLong() {
            return Long.parseLong(nextToken());
        }

        double nextDouble() {
            return Double.parseDouble(nextToken());
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值