Codeforces Round #378 (Div. 2)

Codeforces Round #378 (Div. 2)

A. Grasshopper And the String

题意:
输入一个长度n不超过100的由英文大写字母组成的字符串,元音字母定义为'A','E','I','O','U','Y',起点为字符串的第一个字符的前一个位置,终点为字符串的最后一个字符的下一个位置,一只蟋蟀要从起点跳到终点,其中它每一步只能跳落到靠右最近邻的元音字符所在的位置,求从起点跳到终点的每一步中的最大步长为多少。

分析:
时间复杂度为O(n)。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 100 + 3;
char arr[maxn];

int main() {
  //freopen("input.txt", "r", stdin);
  //freopen("output.txt", "w", stdout);
  memset(arr, 0, sizeof(arr));
  while (~scanf("%s", arr)) {
    int ans = 0, pre = -1, len = strlen(arr);
    for (int i = 0; i < len; i++) {
      if (arr[i] == 'A' || arr[i] == 'E' || arr[i] == 'I' || \
        arr[i] == 'O' || arr[i] == 'U' || arr[i] == 'Y') {
        ans = max(ans, i - pre);
        pre = i;
      }
    }
    ans = max(ans, len - pre);
    printf("%d\n", ans);
    memset(arr, 0, sizeof(arr));
  }
  return 0;
}

B. Parade

题意:
在举办一个阅兵仪式,总共有n(1<=n<=10^5)列士兵,第i列有li(1<=li<=500)个士兵走步时是左脚起步的,有ri(1<=ri<=500)个士兵走步时是右脚起步的,这个阅兵仪式的美感程度可以如下衡量:如果L是n列士兵中左脚起步的士兵的数量,R是n列士兵中右脚起步的士兵的数量,那么美观程度就是|L-R|。你可以也仅可以让其中一列士兵中左脚起步的士兵改用右脚起步、右脚起步的士兵改用左脚起步。现要求应该让哪一列士兵做改变使得美观程度最大,输出列的编号,如果不做改变就已经达到最大的美观程度,就输出0。

分析:
计算不做任何改变时的美观程度,再枚举对每一列做改变是否有提高美观值。时间复杂度为O(n)。

代码如下:

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

const int maxn = 1e5 + 3;
int sum_ll[maxn], sum_rr[maxn], n;

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();
  }
}

int main() {
  //freopen("input.txt", "r", stdin);
  //freopen("output.txt", "w", stdout);
  while (~scanf("%d", &n)) {
    sum_ll[0] = sum_rr[0] = 0;
    for (int i = 1; i <= n; i++) {
      int ll, rr;
      read(ll); read(rr);
      sum_ll[i] = sum_ll[i - 1] + ll;
      sum_rr[i] = sum_rr[i - 1] + rr;
    }
    int ans_idx = 0, ans = abs(sum_ll[n] - sum_rr[n]);
    for (int i = 1; i <= n; i++) {
      int ll = sum_ll[i] - sum_ll[i - 1];
      int rr = sum_rr[i] - sum_rr[i - 1];
      int rest_sum_ll = sum_ll[n] - ll;
      int rest_sum_rr = sum_rr[n] - rr;
      int buf = abs(rest_sum_ll + rr - rest_sum_rr - ll);
      if (buf > ans) { ans = buf; ans_idx = i; }
    }
    printf("%d\n", ans_idx);
  }
  return 0;
}

D. Kostya the Sculptor

题意:
给出n(1<=n<=10^5)个长方体雕塑,每个长方体有长宽高为ai,bi和ci(1<=ai,bi,ci<=10^9)。现要送给一个朋友一个球形雕塑,你可以从n个长方体雕塑中选一个来雕塑,也可以从n个长方体中选两个(要求这两个长方体有一个面是完全吻合的,即长宽相等)长方体粘合在一起(完全相同的面粘在一起)来雕塑,为使得这个球形雕塑体积最大,问该如何选取长方体来雕塑。

分析:
贪心。为使球形雕塑体积最大,即使直径最大,直径即等于选取的一个长方体或黏合后的长方体的最短边的边长。先按只从中选取一个长方体,枚举选中每个长方体得到的直径,记录之中的最大直径,再将这些个长方体按照最长边、次长边、最短边的优先级来比较,排序这些长方体,因为选取两个长方体的目的是为了使得原来的最短边变大,因而若某两个长方体最长边和次长边相等(即可以黏合),则它们一定相邻,因此枚举每一对相邻的长方体,判断是否可以黏合,若可以黏合的话则记录最优直径,最后比较只选取一个长方体和选取两个长方体的最优直径即可。时间复杂度为O(nlogn)。

代码如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <cctype>
#include <algorithm>
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 = 100000 + 3;
int n, one_val, one_idx, two_val, two_idx_1, two_idx_2;

struct Node {
  int a, b, c, idx;
  Node(int aa, int bb, int cc, int _idx): a(aa), b(bb), c(cc), idx(_idx) {}
  bool operator < (const Node& rhs) const {
    if (a != rhs.a) return a > rhs.a;
    else if (b != rhs.b) return b > rhs.b;
    else return c > rhs.c;
  }
};

vector<Node> cube;

void solve() {
  two_val = -1;
  int bound = cube.size();
  for (int i = 0; i < bound - 1; i++) {
    if (cube[i].a == cube[i + 1].a && cube[i].b == cube[i + 1].b) {
      int buf = min(min(cube[i].a, cube[i].b), cube[i].c + cube[i + 1].c);
      if (buf > two_val) {
        two_val = buf;
        two_idx_1 = cube[i].idx;
        two_idx_2 = cube[i + 1].idx;
      }
    }
  }
  if (two_val > one_val) printf("2\n%d %d\n", two_idx_1, two_idx_2);
  else printf("1\n%d\n", one_idx);
}

int main() {
  //freopen("input.txt", "r", stdin);
  while (~scanf("%d", &n)) {
    cube.clear();
    one_val = -1;
    for (int i = 1; i <= n; i++) {
      int a, b, c;
      read(a); read(b); read(c);
      if (a < b) swap(a, b);
      if (a < c) swap(a, c);
      if (b < c) swap(b, c);
      cube.push_back(Node(a, b, c, i));
      if (c > one_val) { one_val = c; one_idx = i; }
    }
    sort(cube.begin(), cube.end());
    if (n == 1) printf("1\n%d\n", one_idx);
    else solve();
  }
  return 0;
}

转载于:https://www.cnblogs.com/huangzhihao/p/6149449.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值