AtCoder Beginner Contest 391个人题解(A-F)

A - Lucky Direction

Time Limit: 2 sec / Memory Limit: 1024 MB

Problem Statement

You are given a string DDD representing one of the eight directions (north, east, west, south, northeast, northwest, southeast, southwest). The correspondence between the directions and their representing strings is as follows.

  • North: N
  • East: E
  • West: W
  • South: S
  • Northeast: NE
  • Northwest: NW
  • Southeast: SE
  • Southwest: SW

Print the string representing the direction opposite to the direction denoted by DDD.

给你一个字符串 DDD 代表八个方向(北、东、西、南、东北、西北、东南、西南)之一。方向与其代表字符串之间的对应关系如下。

  • N
  • 东:`E
  • 西: W
  • 南: S
  • 东北: NE
  • 西北: NW
  • 东南:`SE
  • 西南: SW

打印与 DDD 表示的方向相反的字符串。

Constraints

  • DDD is one of N, E, W, S, NE, NW, SE, SW.

  • DDDNEWSNENWSESW 中的一个。

题解

DDD 中的 N 替换为 SS 替换为 NE 替换为 WW 替换为 E 即可。

s = input()
ns = ''
for i in s:
    if i == 'N':
        ns += 'S'
    elif i=='S':
        ns += 'N'
    elif i=='W':
        ns += 'E'
    else:
        ns += 'W'
print(ns)

B - Seek Grid

Time Limit: 2 sec / Memory Limit: 1024 MB

Problem Statement

You are given an N×NN \times NN×N grid SSS and an M×MM \times MM×M grid TTT. The cell at the iii-th row from the top and the jjj-th column from the left is denoted by (i,j)(i,j)(i,j).

The colors of the cells in SSS and TTT are represented by N2N^2N2 characters Si,jS_{i,j}Si,j (1≤i,j≤N1\leq i,j\leq N1i,jN) and M2M^2M2 characters Ti,jT_{i,j}Ti,j (1≤i,j≤M1\leq i,j\leq M1i,jM), respectively. In grid SSS, cell (i,j)(i,j)(i,j) is white if Si,jS_{i,j}Si,j is ., and black if Si,jS_{i,j}Si,j is #. The same applies for grid TTT.

Find TTT within SSS. More precisely, output integers aaa and bbb (1≤a,b≤N−M+11 \leq a,b \leq N-M+11a,bNM+1) that satisfy the following condition:

  • Sa+i−1,b+j−1=Ti,jS_{a+i-1,b+j-1} = T_{i,j}Sa+i1,b+j1=Ti,j for every i,ji,ji,j (1≤i,j≤M1\leq i,j \leq M1i,jM).

给你一个 N×NN \times NN×N 网格 SSS 和一个 M×MM \times MM×M 网格 TTT 。位于从上往下第 iii 行和从左往上第 jjj 列的单元格用 (i,j)(i,j)(i,j) 表示。

SSSTTT 中单元格的颜色分别用 N2N^2N2 字符 Si,jS_{i,j}Si,j1≤i,j≤N1\leq i,j\leq N1i,jN )和 M2M^2M2 字符 Ti,jT_{i,j}Ti,j1≤i,j≤M1\leq i,j\leq M1i,jM )表示。在网格 SSS 中,如果 Si,jS_{i,j}Si,j 为".",则单元格 (i,j)(i,j)(i,j) 为白色;如果 Si,jS_{i,j}Si,j 为 “#”,则单元格 (i,j)(i,j)(i,j) 为黑色。网格 TTT 也是如此。

SSS 中找到 TTT 。更精确地说,输出满足以下条件的整数 aaabbb1≤a,b≤N−M+11 \leq a,b \leq N-M+11a,bNM+1 ):

  • 每个 i,ji,ji,j ( 1≤i,j≤M1\leq i,j \leq M1i,jM ) 都有 Sa+i−1,b+j−1=Ti,jS_{a+i-1,b+j-1} = T_{i,j}Sa+i1,b+j1=Ti,j 个整数。

Constraints

  • 1≤M≤N≤501 \leq M \leq N \leq 501MN50
  • NNN and MMM are integers.
  • NNNMMM 都是整数。
  • Each of Si,jS_{i,j}Si,j and Ti,jT_{i,j}Ti,j is . or #.
  • Si,jS_{i,j}Si,jTi,jT_{i,j}Ti,j 中的每一个都是 .#
  • There is exactly one pair (a,b)(a,b)(a,b) satisfying the condition.
  • 正好有一对 (a,b)(a,b)(a,b) 满足条件。

题解

暴力遍历所有可能得左上角,如果匹配则输出。

def solve():  
    n, m = map(int, input().split())
    gs = [list(input()) for i in range(n)]
    gt = [list(input()) for i in range(m)]
    for bx in range(n-m+1):
        for by in range(n-m+1):
            f = 1
            for x in range(m):
                for y in range(m):
                    if gt[x][y] != gs[bx+x][by+y]:
                        f = 0
                        break
                if not f:
                    break
            if f:
                print(bx+1, by+1)
                return 
solve()

C - Pigeonhole Query

Time Limit: 2 sec / Memory Limit: 1024 MB

Problem Statement

There are NNN pigeons numbered from 111 to NNN, and there are NNN nests numbered from 111 to NNN. Initially, pigeon iii is in nest iii for 1≤i≤N1\leq i\leq N1iN.

You are given QQQ queries, which you must process in order. There are two types of queries, each given in one of the following formats:

  • 1 P H : Move pigeon PPP to nest HHH.
  • 2 : Output the number of nests that contain more than one pigeon.

NNN 只鸽子,编号从 111NNN ,有 NNN 个鸽巢,编号从 111NNN 。最初,鸽子 iii1≤i≤N1\leq i\leq N1iN 的巢 iii 中。

您会收到 QQQ 个查询,您必须按顺序处理这些查询。查询有两种类型,每种都以下列格式之一给出:

  • 1 P H : 将鸽子 PPP 移至鸽巢 HHH
  • 2 : 输出包含一只以上鸽子的鸽巢数量。

Constraints

  • 2≤N≤1062 \leq N \leq 10^62N106

  • 1≤Q≤3×1051 \leq Q \leq 3\times 10^51Q3×105

  • 1≤P,H≤N1 \leq P, H \leq N1P,HN

  • For a query of the first type, pigeon PPP is not in nest HHH before the move.

  • All input values are integers.

  • 对于第一种类型的查询,鸽子 PPP 在移动前不在鸽巢 HHH 中。

  • 所有输入值均为整数。

题解

我们维护下两个信息

  • 每只鸽子在那个鸽巢

  • 每只鸽巢有几只鸽子

这可以用数组或map完成

为高效统计包含一只以上鸽子的鸽巢数量,每次查询时不去遍历所有的鸽巢。有以下关系

  • 当有鸽巢中的鸽子的数量由 222 变为 111 后,满足条件的鸽巢数量 −1-11

  • 当有鸽巢中的鸽子的数量由 111 变为 222 后,满足条件的鸽巢数量 +1+1+1

只需要在某个鸽巢的鸽子的数量发生变化时判断包含一只以上鸽子的鸽巢数量有无变化即可

n, q = map(int, input().split())
nest = {i:1 for i in range(1, n+1)} # i鸽巢有几只鸽子
check = {i:i for i in range(1, n+1)} # i鸽子在那个鸽巢
number = 0

for _ in range(q):
    cmd = list(map(int, input().split()))
    if cmd[0] == 1:
        p, h = cmd[1:]
        nest[check[p]] -= 1
        if nest[check[p]] == 1:  # 鸽子的数量由2变为1
            number -=1
        check[p] = h # 换鸽巢
        nest[check[p]] += 1
        if nest[check[p]] == 2:  # 鸽子的数量由1变为2
            number +=1
    else:
        print(number)

D - Gravity

Time Limit: 2 sec / Memory Limit: 1024 MB

Problem Statement

There is a grid with 10910^9109 rows and WWW columns. The cell at the xxx-th column from the left and the yyy-th row from the bottom is denoted by (x,y)(x,y)(x,y).

There are NNN blocks. Each block is a 1×11 \times 11×1 square, and block iii-th (1≤i≤N1 \leq i \leq N1iN) is located at cell (Xi,Yi)(X_i,Y_i)(Xi,Yi) at time 000.

At times t=1,2,…,10100t=1,2,\dots,10^{100}t=1,2,,10100, the blocks are moved according to the following rules:

  • If the entire bottom row is filled with blocks, then all blocks in the bottom row are removed.
  • For each remaining block, in order from bottom to top, perform the following:
    • If the block is in the bottom row, or if there is a block in the cell immediately below it, do nothing.
    • Otherwise, move the block one cell downward.

You are given QQQ queries. For the jjj-th query (1≤j≤Q1 \leq j \leq Q1jQ), answer whether block AjA_jAj exists at time Tj+0.5T_j+0.5Tj+0.5.

有一个网格,网格中有 10910^9109 行和 WWW 列。从左边起第 xxx 列和从**底部起第 yyy 行的单元格用 (x,y)(x,y)(x,y) 表示。

共有 NNN 个图块。每个图块是一个 1×11 \times 11×1 正方形,图块 iii1≤i≤N1 \leq i \leq N1iN )位于时间 000(Xi,Yi)(X_i,Y_i)(Xi,Yi) 单元格。

在时间 t=1,2,…,10100t=1,2,\dots,10^{100}t=1,2,,10100 时,这些图块会根据以下规则移动:

  • 如果整个底行都布满了图块,那么底行的所有图块都会被移走。
  • 对于剩余的每个图块,按照从下到上的顺序,执行以下操作:
    • 如果该图块位于最下面一行,或者它下面的单元格中有一个图块,则不做任何操作。
    • 否则,将该图块向下移动一格。

给你 QQQ 个查询。对于 jjj -查询( 1≤j≤Q1 \leq j \leq Q1jQ ),请回答在 Tj+0.5T_j+0.5Tj+0.5 时间块 AjA_jAj 是否存在。

Constraints

  • 1≤N≤2×1051 \leq N \leq 2 \times 10^51N2×105
  • 1≤W≤N1 \leq W \leq N1WN
  • 1≤Xi≤W1 \leq X_i \leq W1XiW
  • 1≤Yi≤1091 \leq Y_i \leq 10^91Yi109
  • (Xi,Yi)≠(Xj,Yj)(X_i,Y_i) \neq (X_j,Y_j)(Xi,Yi)=(Xj,Yj) if i≠ji \neq ji=j.
  • 1≤Q≤2×1051 \leq Q \leq 2 \times 10^51Q2×105
  • 1≤Tj≤1091 \leq T_j \leq 10^91Tj109
  • 1≤Aj≤N1 \leq A_j \leq N1AjN
  • All input values are integers.
  • 所有输入值均为整数。

题解

我们定义 lvlx,y=ilvl_{x, y} = ilvlx,y=i 为对于 xxx 相同的点中,当前点的 yyy 是第 iii 小 。

由题意可知每次被消除的点的 lvllvllvl 一定相同。

而每一 lvllvllvl 被消除要满足

  • 这一层有 www 个点
  • 所有点都到了 y=1y = 1y=1

不难想到, 每一 lvllvllvl 被消除的时间取决于这一 lvllvllvl 的点中 yyy 的最大值。

对每一 lvllvllvl ,最上方的点到达 y=1y=1y=1 的时间为 yi−1y_i - 1yi1, 下一秒这一层的点被消除。

又有 第 lvllvllvl 层的点至少在 lvl−1lvl - 1lvl1 层消除后一秒才会被消除。

我们预处理每个点在那一秒被消除了,之后 O(1)O(1)O(1) 回答每个询问即可。

from collections import defaultdict

n, w = map(int, input().split())
ans  = [10**9+7 for i in range(n+1)]
place = defaultdict(list)
level = defaultdict(list)
mxlvl = 0
for _ in range(n):
    x, y = map(int, input().split())
    place[x].append([y,_])
for nx in place:
    place[nx].sort()
for nx in place:
    mxlvl = max(mxlvl, len(place[nx]))
    for lvl in range(len(place[nx])):
        level[lvl+1].append(place[nx][lvl])
pre = 0
for lv in range(1, mxlvl + 1):
    if len(level[lv]) == w:
        mxy = max(level[lv], key=lambda x:x[0])[0]
        for y, idx in level[lv]:
            ans[idx] = max(mxy, pre+1)
        pre = mxy
q = int(input())
for _ in range(q):
    t, a = map(int, input().split())
    t += 0.5
    a -= 1
    if t > ans[a]:
        print('No')
    else:
        print('Yes')

E - Hierarchical Majority Vote

Time Limit: 2 sec / Memory Limit: 1024 MB

Problem Statement

For a binary string B=B1B2…B3nB = B_1 B_2 \dots B_{3^n}B=B1B2B3n of length 3n3^n3n (n≥1n \geq 1n1), we define an operation to obtain a binary string C=C1C2…C3n−1C = C_1 C_2 \dots C_{3^{n-1}}C=C1C2C3n1 of length 3n−13^{n-1}3n1 as follows:

  • Partition the elements of BBB into groups of 333 and take the majority value from each group. That is, for i=1,2,…,3n−1i=1,2,\dots,3^{n-1}i=1,2,,3n1, let CiC_iCi be the value that appears most frequently among B3i−2B_{3i-2}B3i2, B3i−1B_{3i-1}B3i1, and B3iB_{3i}B3i.

You are given a binary string A=A1A2…A3NA = A_1 A_2 \dots A_{3^N}A=A1A2A3N of length 3N3^N3N. Let A′=A1′A' = A'_1A=A1 be the length-111 string obtained by applying the above operation NNN times to AAA.

Determine the minimum number of elements of AAA that must be changed (from 000 to 111 or from 111 to 000) in order to change the value of A1′A'_1A1.

对于长度为 3n3^n3n ( n≥1n \geq 1n1 ) 的二进制字符串 B=B1B2…B3nB = B_1 B_2 \dots B_{3^n}B=B1B2B3n ,我们定义了如下操作来获取长度为 3n−13^{n-1}3n1 的二进制字符串 C=C1C2…C3n−1C = C_1 C_2 \dots C_{3^{n-1}}C=C1C2C3n1

  • BBB 中的元素分成 333 组,并从每组中取多数值。也就是说,对于 i=1,2,…,3n−1i=1,2,\dots,3^{n-1}i=1,2,,3n1 ,让 CiC_iCi 成为 B3i−2B_{3i-2}B3i2B3i−1B_{3i-1}B3i1B3iB_{3i}B3i 中出现频率最高的值。

给你一个长度为 3N3^N3N 的二进制字符串 A=A1A2…A3NA = A_1 A_2 \dots A_{3^N}A=A1A2A3N 。假设 A′=A1′A' = A'_1A=A1 是对 AAA 进行 NNN 次上述运算后得到的长度为 111 的字符串。

求要改变 A1′A'_1A1 的值,必须改变 AAA 中最少多少个元素(从 000 改为 111 或从 111 改为 000 )。

  • NNN is an integer with 1≤N≤131 \leq N \leq 131N13.
  • AAA is a string of length 3N3^N3N consisting of 000 and 111.

Constraints

  • NNN is an integer with 1≤N≤131 \leq N \leq 131N13.
  • NNN 是包含 1≤N≤131 \leq N \leq 131N13 的整数。
  • AAA is a string of length 3N3^N3N consisting of 000 and 111.
  • AAA 是长度为 3N3^N3N 的字符串,由 000111 组成。

题解

不妨先思考 A=000A = 000A=000 时的情况

易得原来的答案为 000 ,要想变为 111,我们至少要改变两个 000111,改变每个 000 的代价为 111

我们维护每一次操作过程中每一个组的值,以及更改值的代价。

假如某个组为 000000000 , 更改时选取代价最小的两个 000

假如某个组为 001001001 , 更改时选取代价最小的 000

以此类推我们可以得到最终的最小代价

n = int(input())
s = list(input())

dp = [[0, 0] for i in range(3**(n-1))] # dp[i][0] 为组的值,dp[i][1] 为更改值的最小代价
for i in range(0, len(s), 3):
    c = [0, 0]
    c[int(s[i])] += 1
    c[int(s[i+1])] += 1
    c[int(s[i+2])] += 1
    dp[i//3][0] = 1 if c[1] > c[0] else 0
    dp[i//3][1] = 1 if abs(c[1]-c[0]) == 1 else 2
s = n-2
for r in range(n-1):
    ndp = [[0, 0] for i in range(3**s)]
    for i in range(0, len(dp), 3):
        c = [0, 0]
        cost = [[], []]
        for j in range(3):
            c[dp[i+j][0]] += 1
            cost[dp[i+j][0]].append(dp[i+j][1])
        ndp[i//3][0] = 1 if c[1] > c[0] else 0
        n = len(cost[0])
        m = len(cost[1])
        k = cost[ndp[i//3][0]]
        k.sort()
        need = (max(n, m) - min(n, m) + 1)//2
        ndp[i//3][1] = sum(k[:need])
    dp = ndp
    s -= 1
print(dp[0][1])

F - K-th Largest Triplet

Time Limit: 3 sec / Memory Limit: 1024 MB

Problem Statement

You are given three integer sequences of length NNN, namely A=(A1,A2,…,AN)A=(A_1,A_2,\ldots,A_N)A=(A1,A2,,AN), B=(B1,B2,…,BN)B=(B_1,B_2,\ldots,B_N)B=(B1,B2,,BN), and C=(C1,C2,…,CN)C=(C_1,C_2,\ldots,C_N)C=(C1,C2,,CN), and an integer KKK.

For each of the N3N^3N3 choices of integers i,j,ki,j,ki,j,k (1≤i,j,k≤N1\leq i,j,k\leq N1i,j,kN), compute the value AiBj+BjCk+CkAiA_iB_j + B_jC_k + C_kA_iAiBj+BjCk+CkAi. Among all these values, find the KKK-th largest value.

给你三个长度为 NNN 的整数序列,即 A=(A1,A2,…,AN)A=(A_1,A_2,\ldots,A_N)A=(A1,A2,,AN)B=(B1,B2,…,BN)B=(B_1,B_2,\ldots,B_N)B=(B1,B2,,BN)C=(C1,C2,…,CN)C=(C_1,C_2,\ldots,C_N)C=(C1,C2,,CN) 以及一个整数 KKK

对于 N3N^3N3 中的每一个整数 i,j,ki,j,ki,j,k1≤i,j,k≤N1\leq i,j,k\leq N1i,j,kN ),计算其值 AiBj+BjCk+CkAiA_iB_j + B_jC_k + C_kA_iAiBj+BjCk+CkAi 。在所有这些值中,找出 第 KKK 大的值。

Constraints

  • 1≤N≤2×1051\leq N \leq 2\times 10^51N2×105
  • 1≤K≤min⁡(N3,5×105)1\leq K \leq \min(N^3,5\times 10^5)1Kmin(N3,5×105)
  • 1≤Ai,Bi,Ci≤1091\leq A_i,B_i,C_i \leq 10^91Ai,Bi,Ci109
  • All input values are integers.
  • 所有输入值均为整数。

题解

观察到 K≤5×105K \leq 5\times 10^5K5×105,因此算出 KKK 个最大值是可行的。

我们可以用类似 BFSBFSBFS 的方式来进行。

首先对 AAA, BBB, CCC 降序排序。

初始我们将 f(0,0,0),0,0,0f(0, 0, 0), 0, 0, 0f(0,0,0),0,0,0 放入队列中

每一次,我们取出队列中的最大值和对应的 i,j,ki, j, ki,j,k,并尝试i+1,j,ki+1, j, ki+1,j,ki,j+1,ki, j+1, ki,j+1,ki,j,k+1i, j, k+1i,j,k+1

累计执行了 KKK 次后即得到了答案。

#include <bits/stdc++.h>
using namespace std;
  
typedef long long ll;
typedef pair<long long,long long> PLL;
typedef tuple<ll,ll,ll> TLLL;
const ll inf =  0x3f3f3f3f;
const ll INF = INT_MAX;
const ll MOD = 1000000007;
const ll mod = 998244353;
  
inline ll read(){
    ll s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}
   
inline void pt(ll x){if(x<0) putchar('-'),x=-x;if(x>9) pt(x/10);putchar(x%10+'0');}
   
void print(ll x){pt(x), puts("");}
ll encode(ll i, ll j, ll k){
    return (i<<40)|(j<<20)|k;
}

bool cmp(ll x, ll y){
    return x > y;
}

void printVector(vector<ll> vec){
    for(const auto t:vec){
        pt(t),putchar(' ');
    }
    puts("");
}

void solve(){
    ll n = read(), k = read();
    vector<ll> a(n), b(n), c(n);
    for(ll i=0;i<n;i++) a[i] = read();
    for(ll i=0;i<n;i++) b[i] = read();
    for(ll i=0;i<n;i++) c[i] = read();
    sort(a.begin(), a.end(), cmp);
    sort(b.begin(), b.end(), cmp);
    sort(c.begin(), c.end(), cmp);
    auto f = [&](ll i, ll j, ll k){
        return a[i]*b[j] + a[i]*c[k] + b[j]*c[k];
    };
    priority_queue<array<ll, 4>> pq;
    pq.push({f(0, 0, 0), 0, 0, 0});
    
    ll ans = 0;
    unordered_set<ll> used;
    used.insert(encode(0, 0, 0));
    while(k--){
        auto [val, i, j, k] = pq.top();
        pq.pop();
        ans = val;
        if(i + 1< n){
            ll code = encode(i+1, j, k);
            if(used.find(code)==used.end()){
                used.insert(code);
                pq.push({f(i+1, j, k), i+1, j, k});
            }
        }
        if(j + 1< n){
            ll code = encode(i, j+1, k);
            if(used.find(code)==used.end()){
                used.insert(code);
                pq.push({f(i, j+1, k), i, j+1, k});
            }
        }
        if(k + 1< n){
            ll code = encode(i, j, k + 1);
            if(used.find(code)==used.end()){
                used.insert(code);
                pq.push({f(i, j, k+1), i, j, k + 1});
            }
        }
    }
    print(ans);
}

int main(){
    ll t = 1;
    //t = read();
    while(t--){
        solve();
    }
}

G Many LCS (还没做出来)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值