zoukankan      html  css  js  c++  java
  • Codeforces Round #535 (Div. 3)

    A. Two distinct points

    You are given two segments [l1;r1] and [l2;r2] on the x-axis. It is guaranteed that l1<r1 and l2<r2. Segments may intersect, overlap or even coincide with each other.

    Your problem is to find two integers a and b such that l1≤a≤r1, l2≤b≤r2 and a≠b. In other words, you have to choose two distinct integer points in such a way that the first point belongs to the segment [l1;r1] and the second one belongs to the segment [l2;r2].

    It is guaranteed that the answer exists. If there are multiple answers, you can print any of them.

    You have to answer q independent queries.

    Input
    The first line of the input contains one integer q (1≤q≤500) — the number of queries.

    Each of the next q lines contains four integers l1i,r1i,l2i and r2i (1≤l1i,r1i,l2i,r2i≤109,l1i<r1i,l2i<r2i) — the ends of the segments in the i-th query.

    Output
    Print 2q integers. For the i-th query print two integers ai and bi — such numbers that l1i≤ai≤r1i, l2i≤bi≤r2i and ai≠bi. Queries are numbered in order of the input.

    It is guaranteed that the answer exists. If there are multiple answers, you can print any.

    Example
    input
    5
    1 2 1 2
    2 6 3 4
    2 4 1 3
    1 2 1 3
    1 4 5 8
    output
    2 1
    3 4
    3 2
    1 2
    3 7

    题意:给出L1, R1, L2, R2,求两个数满足L1 <= a <= R1, L2 <= b <= R2, a != b。

    思路:先仔细读题。。开始我连a != b都没注意到真是@#%¥。为了节约时间考虑各种特判我直接粗暴的进行了两重for循环,,反正不会TLE。

    代码:略

    B. Divisors of Two Integers

    Recently you have received two positive integer numbers x and y. You forgot them, but you remembered a shuffled list containing all divisors of x (including 1 and x) and all divisors of y (including 1 and y). If d is a divisor of both numbers x and y at the same time, there are two occurrences of d in the list.

    For example, if x=4 and y=6 then the given list can be any permutation of the list [1,2,4,1,2,3,6]. Some of the possible lists are: [1,1,2,4,6,3,2], [4,6,1,1,2,3,2] or [1,6,3,2,4,1,2].

    Your problem is to restore suitable positive integer numbers x and y that would yield the same list of divisors (possibly in different order).

    It is guaranteed that the answer exists, i.e. the given list of divisors corresponds to some positive integers x and y.

    Input
    The first line contains one integer n (2≤n≤128) — the number of divisors of x and y.

    The second line of the input contains n integers d1,d2,…,dn (1≤di≤104), where di is either divisor of x or divisor of y. If a number is divisor of both numbers x and y then there are two copies of this number in the list.

    Output
    Print two positive integer numbers x and y — such numbers that merged list of their divisors is the permutation of the given list of integers. It is guaranteed that the answer exists.

    Example
    input
    10
    10 2 8 1 2 4 1 20 4 5
    output
    20 8

    题意:给出n个数,他们是两个数x, y的因子,求出x, y。特别地,如果某个数是x, y的公因子,它会出现两次。

    思路:考虑到n不大,先粗暴地从大到小排序,根据性质易得当前最大数便是x, y其中较大一个;然后依次从数列中删去该数的因子,剩下的数中那个最大数即x, y其中较小一个。

    代码:略

    C. Nice Garland

    You have a garland consisting of n lamps. Each lamp is colored red, green or blue. The color of the i-th lamp is si ('R', 'G' and 'B' — colors of lamps in the garland).

    You have to recolor some lamps in this garland (recoloring a lamp means changing its initial color to another) in such a way that the obtained garland is nice.

    A garland is called nice if any two lamps of the same color have distance divisible by three between them. I.e. if the obtained garland is t, then for each i,j such that ti=tj should be satisfied |i−j| mod 3=0. The value |x| means absolute value of x, the operation x mod y means remainder of x when divided by y.

    For example, the following garlands are nice: "RGBRGBRG", "GB", "R", "GRBGRBG", "BRGBRGB". The following garlands are not nice: "RR", "RGBG".

    Among all ways to recolor the initial garland to make it nice you have to choose one with the minimum number of recolored lamps. If there are multiple optimal solutions, print any of them.

    Input
    The first line of the input contains one integer n (1≤n≤2⋅105) — the number of lamps.

    The second line of the input contains the string s consisting of n characters 'R', 'G' and 'B' — colors of lamps in the garland.

    Output
    In the first line of the output print one integer r — the minimum number of recolors needed to obtain a nice garland from the given one.

    In the second line of the output print one string t of length n — a nice garland obtained from the initial one with minimum number of recolors. If there are multiple optimal solutions, print any of them.

    Examples
    input
    3
    BRB
    output
    1
    GRB

    input
    7
    RGBGRBB
    output
    3
    RGBRGBR

    题意:包含RGB三个字符的一个数列,要求更换部分字符,使其任意相同字符之间的间距大于2,举个例子,RBGR,合法;RBR,不合法。

    思路:很巧妙的一道题,注意到如果要满足RGB三个字符同时满足题目条件,只有诸如RGBRGBRG...或者GRBGRBGRB...的数列满足。这样我们可以暴力地打出6种有限循环数列的情况,然后和原数列进行比较,字符不同个数最少的数列为满足题意的答案。

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define MAXN 200005
     5 #define INF 1 << 30
     6 
     7 const int num[6][3] = {
     8 {1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1}
     9 };
    10 
    11 int n, a[MAXN], tot, ans = INF, x;
    12 char ch[MAXN];
    13 
    14 int main() {
    15     scanf("%d", &n);
    16     scanf("%s", ch + 1);
    17     for (int i = 1; i <= n; i++) a[i] = ch[i] == 'R' ? 1 : ch[i] == 'G' ? 2 : 3;
    18     for (int i = 0; i <= 5; i++) {
    19         tot = 0;
    20         for (int j = 1; j <= n; j++) tot += a[j] != num[i][j % 3];
    21         if (tot < ans) ans = tot, x = i;
    22     }
    23     printf("%d
    ", ans);
    24     for (int i = 1; i <= n; i++) printf(num[x][i % 3] == 1 ? "R" : num[x][i % 3] == 2 ? "G" : "B");
    25 }

    D. Diverse Garland

    You have a garland consisting of n lamps. Each lamp is colored red, green or blue. The color of the i-th lamp is si ('R', 'G' and 'B' — colors of lamps in the garland).

    You have to recolor some lamps in this garland (recoloring a lamp means changing its initial color to another) in such a way that the obtained garland is diverse.

    A garland is called diverse if any two adjacent (consecutive) lamps (i. e. such lamps that the distance between their positions is 1) have distinct colors.

    In other words, if the obtained garland is t then for each i from 1 to n−1 the condition ti≠ti+1 should be satisfied.

    Among all ways to recolor the initial garland to make it diverse you have to choose one with the minimum number of recolored lamps. If there are multiple optimal solutions, print any of them.

    Input
    The first line of the input contains one integer n (1≤n≤2⋅105) — the number of lamps.

    The second line of the input contains the string s consisting of n characters 'R', 'G' and 'B' — colors of lamps in the garland.

    Output
    In the first line of the output print one integer r — the minimum number of recolors needed to obtain a diverse garland from the given one.

    In the second line of the output print one string t of length n — a diverse garland obtained from the initial one with minimum number of recolors. If there are multiple optimal solutions, print any of them.

    Examples
    input
    9
    RBGRRBRGG
    output
    2
    RBGRGBRGR
    input
    8
    BBBGBRRR
    output
    2
    BRBGBRGR
    input
    13
    BBRRRRGGGGGRR
    output
    6
    BGRBRBGBGBGRG

    题意:包含RGB三个字符的一个数列,要求更换部分字符,使其任意相同字符不相邻。

    思路:D和C算是姊妹题吧,不过思路完全不一样,个人觉得D题思路更容易得出,主要是样例给得相当完美了。从样例中我们容易得出,我们可以对所有连着字符都相同的子串进行拆分,然后对其隔一个字符修改一个,对于连续个数为奇数的情况,修改非最左端右端的字符,修改后的字符只需满足非原字符即可,如GGGGG可修改为GBGBG;对于连续个数为偶数的情况,如果从最左端开始修改,则需考虑该连续字符子串左端的字符,修改后的字符应与其不同,如BGGGG可修改为BRGRG。不过可以不这样特殊考虑,详细见代码。

    代码:

     1 #include <bits/stdc++.h>
     2 #define MAXN 200005
     3 
     4 const char col[3] = {'R', 'G', 'B'}; 
     5 int n, ans, r;
     6 char a[MAXN];
     7 
     8 int main() {
     9     scanf("%d", &n);
    10     scanf("%s", a + 1);
    11     for (int l = 1; l < n;) {
    12         if (a[l] == a[l + 1]) {
    13             int tot = 0;
    14             for (int j = l + 1; j <= n + 1; j++, tot++)
    15                 if (a[j] != a[l]) {
    16                     r = j - 1;
    17                     break;
    18                 }
    19             for (int j = l - tot % 2 + 1; j <= r; j += 2)
    20                 for (int k = 0; k <= 2; k++)
    21                     if (col[k] != a[j] && col[k] != a[j - 1]) {
    22                         a[j] = col[k];
    23                         break;
    24                     }
    25             ans += (tot + 1)/ 2;
    26             l = r + 1;
    27         }
    28         else l++;
    29     }
    30     printf("%d
    ", ans);
    31     for (int i = 1; i <= n; i++) printf("%c", a[i]);
    32     return 0;
    33 }

    E1. Array and Segments (Easy version)

    The only difference between easy and hard versions is a number of elements in the array.

    You are given an array a consisting of n integers. The value of the i-th element of the array is ai.

    You are also given a set of m segments. The j-th segment is [lj;rj], where 1≤lj≤rj≤n.

    You can choose some subset of the given set of segments and decrease values on each of the chosen segments by one (independently). For example, if the initial array a=[0,0,0,0,0] and the given segments are [1;3] and [2;4] then you can choose both of them and the array will become b=[−1,−2,−2,−1,0].

    You have to choose some subset of the given segments (each segment can be chosen at most once) in such a way that if you apply this subset of segments to the array a and obtain the array b then the value maxi=1nbi−mini=1nbi will be maximum possible.

    Note that you can choose the empty set.

    If there are multiple answers, you can print any.

    If you are Python programmer, consider using PyPy instead of Python when you submit your code.

    Input
    The first line of the input contains two integers n and m (1≤n≤300,0≤m≤300) — the length of the array a and the number of segments, respectively.

    The second line of the input contains n integers a1,a2,…,an (−106≤ai≤106), where ai is the value of the i-th element of the array a.

    The next m lines are contain two integers each. The j-th of them contains two integers lj and rj (1≤lj≤rj≤n), where lj and rj are the ends of the j-th segment.

    Output
    In the first line of the output print one integer d — the maximum possible value maxi=1nbi−mini=1nbi if b is the array obtained by applying some subset of the given segments to the array a.

    In the second line of the output print one integer q (0≤q≤m) — the number of segments you apply.

    In the third line print q distinct integers c1,c2,…,cq in any order (1≤ck≤m) — indices of segments you apply to the array a in such a way that the value maxi=1nbi−mini=1nbi of the obtained array b is maximum possible.

    If there are multiple answers, you can print any.

    Examples
    input
    5 4
    2 -2 3 1 2
    1 3
    4 5
    2 5
    1 3
    output
    6
    2
    1 4
    input
    5 4
    2 -2 3 1 4
    3 5
    3 4
    2 4
    2 5
    output
    7
    2
    3 2
    input
    1 0
    1000000
    output
    0
    0

    Note
    In the first example the obtained array b will be [0,−4,1,1,2] so the answer is 6.

    In the second example the obtained array b will be [2,−3,1,−1,4] so the answer is 7.

    In the third example you cannot do anything so the answer is 0.

    题意:给出有n个数的数列和m个区间,要求选出部分区间,对于每一区间中的所有数减1,使数列最大值与最小值之差最大。

    思路:

    1、对于任一区间,如果其中包含了最大值与最小值,或者均不包含,则选择该区间对结果没有影响;如果只包含最大值,则不选;只包含最小值,则选。

    2、数列最大值和最小值是随着我们的每一次操作而变化的,并不是某一个确定的数。这里我们可以采取一种较为暴力的方法,即枚举每一个数作为预期最小值。

    3、根据第一条可得,如果区间包含了我们设定的最小值,则选择该区间必然会趋于更优解,这样问题就简化不少了;

    4、综上,方法是,枚举预期最小值,对于该值,选取所有包含该值的区间进行修改,最后算得每一种情况最大最小值之差中最大的情况即可,最坏复杂度为O(n ^ 2 * m)。

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define MAXN 305
     5 #define INF 1 << 30
     6 
     7 int n, m, a[MAXN], l[MAXN], r[MAXN], b[MAXN], ans, ai, at;
     8 
     9 int main() {
    10     scanf("%d %d", &n, &m);
    11     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    12     for (int i = 1; i <= m; i++) scanf("%d %d", &l[i], &r[i]);
    13     for (int i = 1; i <= n; i++) {
    14         int tot = 0, mx = -INF, mi = INF;
    15         for (int j = 1; j <= n; j++) b[j] = a[j];
    16         for (int j = 1; j <= m; j++)
    17             if (l[j] <= i && i <= r[j]) {
    18                 tot++;
    19                 for (int k = l[j]; k <= r[j]; k++) b[k]--;
    20             }
    21         for (int j = 1; j <= n; j++) 
    22             mx = max(b[j], mx), mi = min(b[j], mi);
    23         if (mx - mi > ans) ans = mx - mi, ai = i, at = tot;
    24     }
    25     printf("%d
    %d
    ", ans, at);
    26     for (int i = 1; i <= m; i++)
    27         if (l[i] <= ai && ai <= r[i]) printf("%d ", i);
    28     
    29 } 

    E2. Array and Segments (Hard version)

    题意:题干略。困难版与简单版的唯一区别为n的取值由1 <= n <= 300上调至1 <= n <= 10 ^ 5。

    思路:

    n被加强之后,简单版本的方法显然不适用了。但由于题目从头到尾都是进行区间修改以及区间查询,可以顺理成章地想到线段树。刚开始做的时候备受困扰——难道每次选择一个新的数时都要重新初始化一次线段树嘛??

    看了其他人的思路后才豁然开朗——我们发现,如果我们从选择i为最小值变成选择i + 1时,只有两种区间会出现选择的变化——[x, i],以及[i + 1, y]。对于前者我们将[x, i]全部加1,后者我们将[i + 1, y]全部减1即可。

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define MAXN 100005
     5 #define INF 1 << 30
     6 
     7 int n, m, a[MAXN], l[MAXN], r[MAXN], b[MAXN], tot, ans, ai, ql, qr;
     8 
     9 struct Tree {
    10     int mx, mi, f;
    11 } t[MAXN << 2], ti[MAXN << 2];
    12 
    13 void build(int o, int l, int r) {
    14     if (l == r) {
    15         t[o] = (Tree) {a[l], a[l]};
    16         return;
    17     }
    18     int ls = o << 1, rs = o << 1 | 1, mid = (l + r) >> 1;
    19     build(ls, l, mid), build(rs, mid + 1, r);
    20     t[o] = (Tree) {max(t[ls].mx, t[rs].mx), min(t[ls].mi, t[rs].mi)};
    21 }
    22 
    23 void push(int o) {
    24     int ls = o << 1, rs = o << 1 | 1;
    25     t[ls].mi += t[o].f, t[ls].mx += t[o].f;
    26     t[rs].mi += t[o].f, t[rs].mx += t[o].f;
    27     t[ls].f += t[o].f, t[rs].f += t[o].f;
    28     t[o].f = 0;
    29 }
    30 
    31 void upd(int o, int l, int r, int x) {
    32     int ls = o << 1, rs = o << 1 | 1, mid = (l + r) >> 1;
    33     if (t[o].f) push(o);
    34     if (ql <= l && r <= qr) {
    35         t[o].f += x, t[o].mi += x, t[o].mx += x;
    36         return;
    37     }
    38     if (ql <= mid) upd(ls, l, mid, x);
    39     if (mid + 1 <= qr) upd(rs, mid + 1, r, x);
    40     t[o] = (Tree) {max(t[ls].mx, t[rs].mx), min(t[ls].mi, t[rs].mi)};
    41 }
    42 
    43 int main() {
    44     scanf("%d %d", &n, &m);
    45     for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    46     build(1, 1, n);
    47     for (int i = 1; i <= m; i++) scanf("%d %d", &l[i], &r[i]);
    48     for (int i = 1; i <= n; i++) {
    49         for (int j = 1; j <= m; j++) {
    50             if (i == l[j]) ql = l[j], qr = r[j], upd(1, 1, n, -1);
    51             if (i == r[j] + 1) ql = l[j], qr = r[j], upd(1, 1, n, 1);
    52         }
    53         int mx = t[1].mx, mi = t[1].mi;
    54         if (mx - mi > ans) ans = mx - mi, ai = i;
    55     }
    56     printf("%d
    ", ans);
    57     for (int i = 1; i <= m; i++)
    58         if (l[i] <= ai && ai <= r[i]) tot++;
    59     printf("%d
    ", tot);
    60     for (int i = 1; i <= m; i++)
    61         if (l[i] <= ai && ai <= r[i]) printf("%d ", i);
    62     return 0;
    63 }
  • 相关阅读:
    Prim算法的3个版本
    [转]"undefined reference to" 问题解决方法
    C/C++ 读写 Excel
    Poj 3468
    关于PS中矩形工具的学习
    PS初学习
    java第二天学习。
    Java学习第一天
    二叉树的线索化
    struct files_struct
  • 原文地址:https://www.cnblogs.com/jinkun113/p/10313857.html
Copyright © 2011-2022 走看看