Codeforces Round #375 (Div. 2)

Codeforces Round #375 (Div. 2)

A. The New Year: Meeting Friends

题意:

有三个朋友都是住在Ox轴上,他们的地址分别为x1,x2,x3(1<=x1,x2,x3<=100,且三个数distinct),现在他们打算约一个地点(Ox轴上)见面,一起去庆祝新年,现求一个地点使得他们三个人分别到这个地点的距离之和最短。题目保证最优解为整数。

分析:
朴素求法。时间复杂度为O(1)。

代码如下:

#include <cstdio>
#include <cstring>

inline int MAX(int a, int b) {
	return a > b ? a : b;
}

inline int MIN(int a, int b) {
	return a < b ? a : b;
}

int main() {
	//freopen("input.txt", "r", stdin);
	int x_1, x_2, x_3;
	while (~scanf("%d%d%d", &x_1, &x_2, &x_3)) {
		int min_val = MIN(x_1, MIN(x_2, x_3));
		int max_val = MAX(x_1, MAX(x_2, x_3));
		printf("%d\n", max_val - min_val);
	}
	return 0;
}

B. Text Document Analysis

题意:
给出一个字符串,长度为n(1<=n<=255),这个字符串只由以下三种字符构成:

  • 英文字母(大写或小写)
  • 下划线(用来作为分隔符)
  • 括号(包括左括号和右括号)

题目保证括号都是成对出现的,且每个右括号的之前字符中都存在左括号与之匹配,且每对括号里都不再存在另外一对括号,即括号不可嵌套,定义一个单词为连续出现的英文字母,现需求两个问题,一是求括号外最长单词的长度(如果括号外没有单词,则答案为0),二是求括号内的单词数(如果括号内没有单词,则答案为0)。

分析:
朴素求解。时间复杂度为O(n)。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <utility>
using namespace std;

const int maxn = 255 + 3;
char arr[maxn];
int n;

pair<int, int> solve() {
	int ans_1 = 0, ans_2 = 0;
	for (int i = 1; i <= n; ) {
		if (arr[i] == '_') { ++i; continue; }
		else if (arr[i] == '(') {
			int idx = i + 1;
			while (arr[idx] != ')') {
				if (arr[idx] == '_') idx += 1;
				else if (isalpha(arr[idx])) {
					int ano_idx = idx;
					while (isalpha(arr[ano_idx + 1])) ano_idx += 1;
					ans_2 += 1;
					idx = ano_idx + 1;
				}
			}
			i = idx + 1;
		}
		else if (isalpha(arr[i])) {
			int idx = i;
			while (isalpha(arr[idx + 1])) idx += 1;
			ans_1 = max(ans_1, idx - i + 1);
			i = idx + 1;
		}
	}
	return make_pair(ans_1, ans_2);
}

int main() {
	//freopen("input.txt", "r", stdin);
	memset(arr, 0, sizeof(arr));
	while (~scanf("%d%s", &n, arr + 1)) {
		pair<int, int> ans = solve();
		printf("%d %d\n", ans.first, ans.second);
		memset(arr, 0, sizeof(arr));
	}
	return 0;
}

C. Polycarp at the Radio

题意:

小明是个DJ,他手上现在有n首歌曲(1<=n<=2000),分别为a1,a2,...,an,ai(1<=ai<=10^9)表示的是乐队的编号,表示ai演奏第i首歌,小明喜欢的乐队是编号从1到m(1<=m<=2000)的乐队,定义bj为歌单中乐队j演奏的歌曲数目,现在小明想改变下歌单使得b1,..,bm中的最小数尽量大。求出这个数值,和需要改变歌单的最小次数。其中一次改变定义为将第i首歌的演奏者变为其他任意一个演奏者。

分析:

贪心。不难发现,那个尽量大的最小数即为n/m的下取整,将bj排序,那些小于ans的那些bj就是需要改变的对象,需要增加这些乐队的演奏曲目数。

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;

inline void read(int& buf) {
  buf = 0;
  char c = getchar();
  while (!isdigit(c)) c = getchar();
  while (isdigit(c)) {
    buf = (buf << 3) + (buf << 1) + (c - '0');
    c = getchar();
  }
}

const int maxn = 2000 + 3;
int n, m, a[maxn], cnt[maxn], ans;

struct Node {
  int idx, count;
  Node(int aa, int bb): idx(aa), count(bb) {}
  bool operator < (const Node& rhs) const {
    return count > rhs.count;
  }
};

vector<Node> good;

int solve() {
  int change = 0, st = 0;
  while (good.back().count < ans) {
    Node buf = good.back(); good.pop_back();
    int need = ans - buf.count, now = 0;
    while (now < need) {
      if (a[st] > m) { a[st] = buf.idx; now++; cnt[a[st++]]++; }
      else if (cnt[a[st]] <= ans) st++;
      else {
        cnt[a[st]]--;
        a[st] = buf.idx;
        cnt[a[st++]]++;
        now++;
      }
    }
    change += need;
  }
  return change;
}

int main() {
  //freopen("input.txt", "r", stdin);
  while (~scanf("%d", &n)) {
    read(m);
    memset(cnt, 0, sizeof(cnt));
    for (int i = 1; i <= n; i++) {
      read(a[i]);
      if (a[i] >= 1 && a[i] <= m) cnt[a[i]]++;
    }
    ans = n / m;
    good.clear();
    for (int i = 1; i <= m; i++) good.push_back(Node(i, cnt[i]));
    sort(good.begin(), good.end());
    int change = solve();
    printf("%d %d\n", ans, change);
    for (int i = 1; i <= n; i++) {
      if (i > 1) putchar(' ');
      printf("%d", a[i]);
    }
    puts("");
  }
  return 0;
}

D. Lakes in Berland

题意:

一座小岛的地图是一个n*m(1<=n,m<=50)的长方形,其中每个单元都是一个1*1的小格,每个小格要么是陆地要么是水域,这座小岛的地图是被海洋环绕,湖就是连通的最大水域,但是却又不和海洋连通,正式来定义的话,就是,一个水域小格组成的集合,从这个集合中任意一个水域小格出发,只靠通过相连的边、不离开这个集合中的小格,都可到达集合中任意其他的水域小格,集合中的水域小格都不在矩形的边缘(因为那样便与海洋连通了),且这个集合已经包含了尽量多的水域小格,不然就还可以连通(添加)其他水域小格。你的任务是填上尽量少的水域小格,使得这座小岛上只有恰好k(0<=k<=50)个湖,注意到一开始小岛上的湖的数量不少于k。字符'.'表示水域小格,字符'*'表示陆地。

分析:

连通块+排序。找出图中所有的湖,假设一开始有k0个湖,填上水域格子数最少的k0-k个湖即可。时间复杂度为O(nm+k0*logk0)。

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;

const int maxn = 50 + 3;
char arr[maxn][maxn];
int n, m, k, cells;
vector<pair<int, int> > lake_cells[maxn * maxn];
bool already[maxn][maxn], flag;

const int dx[4] = {-1, 1, 0, 0};
const int dy[4] = {0, 0, -1, 1};

struct Node {
  int idx, cells;
  Node(int aa, int bb): idx(aa), cells(bb) {}
  bool operator < (const Node& rhs) const {
    return cells < rhs.cells;
  }
};

vector<Node> lakes;

inline bool is_in(int x, int y) {
  return (x >= 0 && x < n && y >= 0 && y < m);
}

inline bool is_bound(int x, int y) {
  return (x == 0 || x == n - 1 || y == 0 || y == m - 1);
}

int dfs(int x, int y, int idx) {
  already[x][y] = true;
  lake_cells[idx].push_back(make_pair(x, y));
  int cnt = 1;
  for (int i = 0; i < 4; i++) {
    int nx = x + dx[i], ny = y + dy[i];
    if (!is_in(nx, ny) || arr[nx][ny] == '*' || already[nx][ny]) continue;
    if (is_bound(nx, ny)) { flag = false; continue; }
    cnt += dfs(nx, ny, idx);
  }
  return cnt;
}

void solve() {
  for (int i = 0; i < n * m; i++) lake_cells[i].clear();
  memset(already, 0, sizeof(already));
  lakes.clear();
  int total = -1;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
      if (!is_bound(i, j) && !already[i][j] && arr[i][j] == '.') {
        //printf("(%d,%d) ", i, j);
        flag = true;
        int cnt = dfs(i, j, ++total);
        if (flag) lakes.push_back(Node(total, cnt));
        else lake_cells[total--].clear();
        //flag ? puts("ok") : puts("sorry");
      }
  //printf("#lakes is %d\n", total + 1);
  sort(lakes.begin(), lakes.end());
  int ans = 0;
  for (int i = 0; i < total + 1 - k; i++) {
    ans += lakes[i].cells;
    const vector<pair<int, int> >& buf = lake_cells[lakes[i].idx];
    int bound = buf.size();
    for (int j = 0; j < bound; j++)
      arr[buf[j].first][buf[j].second] = '*';
  }
  printf("%d\n", ans);
  for (int i = 0; i < n; i++) puts(arr[i]);
}

int main() {
  //freopen("input.txt", "r", stdin);
  //freopen("output.txt", "w", stdout);
  while (~scanf("%d%d%d", &n, &m, &k)) {
    memset(arr, 0, sizeof(arr));
    for (int i = 0; i < n; i++) scanf("%s", arr[i]);
    solve();
  }
  return 0;
}
posted @ 2016-12-17 22:20  Alexis Lacour  阅读(206)  评论(0编辑  收藏  举报