您的位置:首页 > 其它

Codeforces Round #339 (Div. 1) ABC

2016-01-16 13:45 225 查看

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
= 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
= 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());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces Round-#339