CodeForces Round 619 (Rated for Div. 2) Pariticipation report

Date: Feb. 13. 2020

CodeForces Round 619 (Rated for Div. 2) Pariticipation report

Since 2019-nCov is still impacting the society.

Taking part in such a competition might be a good choice.

Generally speaking, this round is not so hard.

Let me show the problems:


A. Three Strings

You are given three strings a, b and c of the same length n. For the same index order, you must swap the character in c with the character in either a or b. The problem is if it is possible that after these swaps the string a becomes exactly the same as the string b.

SAMPLE INPUT

4
aaa
bbb
ccc
abc
bca
bca
aabb
bbaa
baba
imi
mii
iim

SAMPLE OUTPUT

NO
YES
YES
NO

To solve it, just compare every character in c to those in a and b for the same index. If all of the character for the same index in a or b is same to c, the answer is YES.

MY CODE

# python3
t = int(input())
for ti in range(t):
    a = input()
    b = input()
    c = input()
    f = 1
    for i in range(len(a)):
        if c[i] in (a[i],b[i]):
            pass
        else:
            print('NO')
            f = 0
            break
    if f:
        print('YES')

B. Motarack's Birthday

You are given an non-negetive array a with some missing elements marked as -1.Try to fill out of all missing elements with the same integer k to make the maximum absolute difference m between all adjacent elements minimized. Output the m and the k.

SAMPLE INPUT

7
5
-1 10 -1 12 -1
5
-1 40 35 -1 35
6
-1 -1 9 -1 3 -1
2
-1 -1
2
0 -1
4
1 -1 3 -1
7
1 -1 7 5 2 -1 5

SAMPLE OUTPUT

1 11
5 35
3 6
0 42
0 0
1 2
3 4

After thinking for about 20 minutes, I find the problem is asking the median of the maximum value and the minimum value.

MY CODE

t = int(input())
for ti in range(t):
    n = int(input())
    li = [int(i) for i in input().split(' ')]
    ss = 0
    cc = 0
    sep = 0
    _min = 1919810114514
    _max = 0
    for idx, i in enumerate(li):

        if i == -1:
            if idx and li[idx-1] != -1:
                _min = min(_min, li[idx-1])
                _max = max(_max, li[idx-1])

        else:
            
            if idx and li[idx-1] != -1:
                sep = max(sep, abs(li[idx-1]-i))
            elif idx and li[idx-1] == -1:
                _min = min(_min, i)
                _max = max(_max, i)
            ss += i
            cc += 1
    if cc:
        # r = round(ss/cc)
        r = (_min+_max)//2
        sep = max(sep,r - _min, _max-r)
        print(sep,r)
    else:
        print(0,0)

C. Ayoub's function

You are given a binary string (a string which contains only symbols "0" and "1") s. Define function f(s) is equal to the number of substring in s that contains at least one symbol of "1".

Now you know the count of "1" in every s. How will you construct s so the f(s) reach the max possible value? Output the maximum value.

SAMPLE INPUT

5
3 1
3 2
3 3
4 0
5 2

SAMPLE OUTPUT

4
5
6
0
12

Since we are finding a construction of s that makes the count of intervals contain "1" as large as possible. We can find that the f(s) is also equal to the total count of substrings in s subtract by the count of intervals contain all "0".

So we just need to make the length of every continuously "0" strings as small as possible.

MY CODE

def getarrsum(n):
    return (1+n)*n//2

t = int(input())
for ti in range(t):
    n, ctr = (int(i) for i in input().split(' '))
    if n == ctr:
        print((1+n)*n//2)
    elif ctr:
        tot = (1+n)*n//2
        c0 = n - ctr
        dvd = c0 // (1+ctr)
        rem = c0 % (1+ctr)
        cur = ctr+1 - rem
        d1 = cur * getarrsum(dvd)
        d2 = rem * getarrsum(dvd+1)
        print(tot-d1-d2)
    else:
        print(0)

D. Time to Run

You are given a map contain n rows and m columns like this:

map

Every path between adjacent cells can be visited at most once. You start at the top-left cell in the grid. If you can move exactly k times, print your route. Otherwise print NO.

SAMPLE INPUT

3 3 8

SAMPLE OUTPUT

YES
8
3 R
3 L
1 D
3 R
1 D
1 U
3 L
1 D

To visit all of the path, you can move like this:

moves

So all we need is to count the moves and check if it can reach k.

CODE COPIED FROM STD

n,m,k= (int(i) for i in input().split(' '))

path = []
tot = 0
for i in range(n):
    path.append((m-1,'R'))
    tot += path[-1][0] * len(path[-1][1])
    if i == 0:
        path.append((m-1,'L'))
    else:
        path.append((m-1,'UDL'))
    tot += path[-1][0] * len(path[-1][1])
    if i == n-1:
        path.append((n-1,'U'))
    else:
        path.append((1,'D'))
    tot += path[-1][0] * len(path[-1][1])

if k > 4*n*m-2*n-2*m:
    print('NO')
else:
    while tot > k:
        tmp = path[-1][1]
        cur = path[-1][0] * len(tmp)
        path.pop()
        tot -= cur
        if tot >= k:
            continue
        cur = k - tot
        if cur // len(tmp) > 0:
            path.append((cur//len(tmp),tmp))

        tmp = tmp[:cur%len(tmp)]
        if len(tmp) > 0:
            path.append((1,tmp))
        tot = k
    print('YES')
    
    p2 = []

    for i in path:
        if i[0]:
            p2.append(i)
    print(len(p2))
    for i,j in p2:
        if i:
            print(i,j)

E. Nanosoft

You are given a picture colored by at most 4 colors: green (the symbol G), red (the symbol R), yellow (the symbol Y) and blue (the symbol B).

We define a picture logo like this:

logo

Can you cut the largest logo from the given picture? Print the size of your logo.

SAMPLE INPUT

5 5 5
RRGGB
RRGGY
YYBBG
YYBBR
RBBRG
1 1 5 5
2 2 5 5
2 2 3 3
1 1 3 5
4 4 5 5

SAMPLE OUTPUT

16
4
4
4
0

I didn't solve this problem actually, here is the official solution:

For each cell, we will calculate the maximum size of a Nanosoft logo in which it is the bottom right cell, in the top left square.

The cell marked with x in this picture:

x

If we had a grid like this:

if

If we take the cell in the second row, second column, it can make a Nanosoft logo with size 4×4, being the bottom right cell in the top left square.

We can calculate the answer for every cell using binary search , and checking every sub-square using 2D cumulative sum.

Now we build a 2D array that contains that previous calculated answer, lets call it val[n][m].

For the previous picture val will be like this:

val

Now for each query we can do binary search on its answer. We check the current mid this way:

The mid will tell us the length of one of the sides divided by 2.

Like if mid = 2, the area of the square we are checking is (4⋅4=16).

Now we should check the maximum element in the 2D array val, in the 2D range: (r1+mid−1,c1+mid−1,r2−mid,c2−mid).

The current mid is correct if the maximum element in that 2D range is greater than or equal to (4⋅mid⋅mid).

We can get the maximum value in a 2D range using 2D sparse table, with build in O(n⋅m⋅logn⋅logm) and query in O(1).

total Complexity is O(n⋅m⋅logn⋅logm+q⋅logm).

But actually it can be tolerate Complexity O(n^3) for the preprocess. That means we are not forced to use binary search.

After the preprocess, each query can be handled in O(1).

STD

#include <bits/stdc++.h>
using namespace std;
#define oo 1000000010
#define mod 1000000007
const int N = 510 , LOG = 10;
char grid[N][N];
int val[N][N] , sum[N][N][4];
int st[N][N][LOG][LOG] , lg[N];
int n , q , m , r1 , c1 , r2, c2 , nr , nc;
 
string S = "RGYB";
int dr[4] = {0 , 0 , 1 , 1};
int dc[4] = {0 , 1 , 0 , 1};
 
inline bool check(int r1,int c1,int r2,int c2,int k){
    r1++,c1++,r2++,c2++;
    return ((sum[r2][c2][k] - sum[r1 - 1][c2][k] - sum[r2][c1 - 1][k] + sum[r1 - 1][c1 - 1][k]) == (r2 - r1 + 1) * (c2 - c1 + 1));
}   
 
inline bool can(int r,int c,int s){
    if(r < 0 || c < 0) return false;
    if(r + (s << 1) - 1 >= n || c + (s << 1) - 1 >= m) return false;
    for(int i =0  ;i < 4;i++){
        nr = r + dr[i] * s ;
        nc = c + dc[i] * s;
        if(!check(nr , nc , nr + s - 1 , nc + s - 1 , i))
            return false;
    }
    return true;
}
 
void build(){
    lg[1] = 0;
    for(int i = 2;i<N;i++){
        lg[i] = lg[i - 1];
        if((1 << (lg[i] + 1)) == i)
            lg[i]++;
    }
    for(int k = 1;k < LOG;k++){
        for(int i=0;i + (1 << k) <= n;i++){
            for(int j=0;j<m;j++){
                st[i][j][k][0] = max(st[i][j][k - 1][0] , st[i + (1 << (k - 1))][j][k - 1][0]);
            }
        }
    }
    for(int l = 1;l < LOG;l++){
        for(int k = 0;k < LOG;k++){
            for(int i=0;i+(1 << k) <= n;i++){
                for(int j = 0;j + (1 << l) <= m;j++){
                    st[i][j][k][l] = max(st[i][j][k][l - 1] , st[i][j + (1 << (l - 1))][k][l-1]);
                }
            }
        }
    }
}
 
int a , b;
 
inline int getmax(int r1,int c1,int r2,int c2){
    if(r2 < r1 || c2 < c1 || r1 < 0 || r2 >= n || c1 < 0 || c2 >= m) return -oo;
    a = lg[(r2 - r1) + 1];
    b = lg[(c2 - c1) + 1];
    return max(max(st[r1][c1][a][b] , st[r2 - (1 << a) + 1][c1][a][b]) , max(st[r1][c2 - (1 << b) + 1][a][b] , st[r2 - (1 << a) + 1][c2 - (1 << b) + 1][a][b]));
}
 
 
int main(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=0;i<n;i++){
        scanf(" %s",grid[i]);
        for(int j=0;j<m;j++){
            for(int k=0;k<4;k++){
                sum[i + 1][j + 1][k] = sum[i][j + 1][k] + sum[i + 1][j][k] - sum[i][j][k] + (S[k] == grid[i][j]);
            }
        }
    }
    int low , high , mid , res;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            low = 1 , high = min(min(i + 1,n - i) , min(j + 1,m - j));
            while(high >= low){
                mid = ((low + high) >> 1);
                if(can(i - mid + 1,j - mid + 1,mid))
                    st[i][j][0][0] = mid, low = mid + 1;
                else
                    high = mid - 1;
            }
        }
    }
    build();
    while(q--){
        scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
        r1--,c1--,r2--,c2--;
        low = 1 , high = (n >> 1) , res = 0;
        while(high >= low){
            mid = ((low + high) >> 1);
            if(getmax(r1 + mid - 1,c1 + mid - 1,r2 - mid , c2 - mid) >= mid)
                res = mid, low = mid + 1;
            else
                high = mid - 1;
        }
        printf("%d\n",res * res * 4);
    }
    return 0;
}

F. Super Jaber

You are given a n rows m columns grids colored by k (k<=40) colors. Every second you can move to adjacent cells or to a cell have the same color as you are standing on. Question is the least time consumption from cell (r1,c1) to cell (r2,c2).

SAMPLE INPUT

3 4 5
1 2 1 3
4 4 5 5
1 2 1 3
2
1 1 3 4
2 2 2 2

SAMPLE OUTPUT

2
0

At first I tend to use double source BFS, but unfortunately timed out.

Having discussed in ACM groups, they show me a solution to preprocess the map in time Complexity O(nmk) and memory Complexity O(nmk). Then for every query, solve it in O(k).

Preprocess the grids like this:

For every cell, calculate the nearest distance of color from 1 to k from it. So for every cell and every color, we have the nearest path saved in array dist. This can be done by multi-source BFS.

Then for every query, we can choose a best color to jump or just normally go to the endpoint without using the same color jump. So initialize the answer to Manhattan distance, literate c from 1 to k, the answer is exactly min(answer,dist[r2][c2][c],dist[r1][c1][c]).

I was worried about this solution as it seems to use same color jump only once. But I found this is not a mistake since every same color jump is done at the BFS.

I have tried to rewrite the solution in Python3, but though I used ctypes library it is too slow to solve the problem.

MY CODE

# coding:utf-8
from ctypes import *

dr = (0, 1, 0, -1)
dc = (1, 0, -1, 0)
# cost = [[0 for i in range(1000000)] for i in range(40)]
cost = (c_int8 * (1000000) * 40)()
class que():
    def __init__(self):

        self.mem = (c_int32 * 1000000)()
        self.l = 0
        self.r = 0
        self.M = 1000000
    def push(self,ar):

        if self.r >= self.M:
            self.r -= self.M

        self.mem[self.r] = ar
        self.r += 1
    def pop(self):
        if self.l >= self.M:
            self.l -= self.M
        self.l += 1
        return self.mem[self.l-1]
    def anything(self):
        return self.r != self.l
    def clear(self):
        self.l = 0
        self.r = 0

q = que()

n, m, k = (int(i) for i in input().split(' '))
grid = []  
cells = [[] for i in range(k)]




def bfs(col):
    q.clear()

    for kk in cells[col]:
        cost[col][kk] = -1
        q.push(kk)
    done = (c_bool * k)()

    while q.anything():

        now = q.pop()
        nx = now // m
        ny = now - nx * m

        now_col = grid[now]
        if not done[now_col]:
            done[now_col] = 1
            for kk in cells[now_col]:
                if 0 == cost[col][kk]:
                    cost[col][kk] = max(0,cost[col][now]) + 1
                    q.push(kk)


        for i in range(4):
            cx,cy = nx+dr[i], ny+dc[i]
            cur = cx*m+cy
            if cx >= 0 and cx < n and \
               cy >= 0 and cy < m and \
               0 == cost[col][cur]:
                cost[col][cur] = max(0,cost[col][now]) + 1
                q.push(cur)




for i in range(n):
    tmp = [int(j)-1 for j in input().split(' ')]
    grid += tmp
    for jd, j in enumerate(tmp):
        cells[j].append(i*m+jd)



for co in range(k):
    bfs(co)

t = int(input())
for ti in range(t):
    x,y,X,Y = (int(i)-1 for i in input().split(' '))
    ans = abs(x-X) + abs(y-Y)
    for i in range(k):
        if cost[i][x*m+y] == -1:
            cost[i][x*m+y] = 0
        if cost[i][X*m+Y] == -1:
            cost[i][X*m+Y] = 0
        ans = min(ans, 1 + cost[i][x*m+y] + cost[i][X*m+Y])
    print(ans)

STD

#include <bits/stdc++.h>
using namespace std;
#define oo 1000000000
#define mod 998244353
const int N = 1010 , K = 45; 
int n , m , k , r1 , r2 , c1 , c2 , grid[N][N] , ans = 0;
 
int cost[K][N][N];
bool done[K];
 
queue < pair<int,int> > q;
 
int dr[4] = {0 , 1 , 0 , -1};
int dc[4] = {1 , 0 ,-1 ,  0};
 
vector < pair<int,int> > cells[K];
 
void BFS(int col){
    for(int i = 0; i < (int)cells[col].size();i++){
        cost[col][cells[col][i].first][cells[col][i].second] = 0;
        q.push(make_pair(cells[col][i].first,cells[col][i].second));
    }
    for(int i = 1;i <= k;i++) done[i] = false;
    int r , c , nr , nc;
    while(!q.empty()){
        r = q.front().first;
        c = q.front().second;
        q.pop();
        if(!done[grid[r][c]]){
            done[grid[r][c]] = true;
            for(int i = 0 ; i < (int)cells[grid[r][c]].size() ;i++){
                nr = cells[grid[r][c]][i].first;
                nc = cells[grid[r][c]][i].second;
                if(cost[col][nr][nc] == -1){
                    cost[col][nr][nc] = cost[col][r][c] + 1;
                    q.push(make_pair(nr , nc));
                }
            }
        }
        for(int i = 0 ;i < 4;i++){
            nr = r + dr[i];
            nc = c + dc[i];
            if(nr >= 0 && nr < n && nc >= 0 && nc < m && cost[col][nr][nc] == -1){
                cost[col][nr][nc] = cost[col][r][c] + 1;
                q.push(make_pair(nr , nc));
            }
        }
    }
}
 
 
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 0 ;i < n;i++){
        for(int j = 0 ;j < m;j++){
            scanf("%d",&grid[i][j]);
            cells[grid[i][j]].push_back(make_pair(i , j));
        }
    }
    memset(cost,  -1, sizeof(cost));
    for(int i = 1;i <= k;i++)
        BFS(i);
    int q;
    scanf("%d",&q);
    while(q--){
        scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
        r1--,c1--,r2--,c2--;
        ans = abs(r1 - r2) + abs(c1 - c2);
        for(int i = 1;i <= k;i++)
            ans = min(ans , 1 + cost[i][r1][c1] + cost[i][r2][c2]);
        printf("%d\n",ans);
    }
    return 0;
}

嘛,为了应付英语日记写成了英语

posted @ 2020-02-16 23:49  昵称不能为空voidf  阅读(217)  评论(0编辑  收藏  举报