USACO 1月 2020-2021 January Contest Silver 题解

Problem 1. Dance Mooves

Farmer John’s cows are showing off their new dance mooves!

At first, all NN cows (2≤N≤1052≤N≤105) stand in a line with cow ii in the iith position in line. The sequence of dance mooves is given by KK (1≤K≤2⋅1051≤K≤2⋅105) pairs of positions (a1,b1),(a2,b2),…,(aK,bK)(a1,b1),(a2,b2),…,(aK,bK). In each minute i=1…Ki=1…K of the dance, the cows in positions aiai and bibi in line swap. The same KK swaps happen again in minutes K+1…2KK+1…2K, again in minutes 2K+1…3K2K+1…3K, and so on, continuing indefinitely in a cyclic fashion. In other words,

  • In minute 11, the cows at positions a1a1 and b1b1 swap.
  • In minute 22, the cows at positions a2a2 and b2b2 swap.
  • ...
  • In minute KK, the cows in positions aKaK and bKbK swap.
  • In minute K+1K+1, the cows in positions a1a1 and b1b1 swap.
  • In minute K+2K+2, the cows in positions a2a2 and b2b2 swap.
  • and so on ...

For each cow, please determine the number of unique positions in the line she will ever occupy.

INPUT FORMAT (input arrives from the terminal / stdin):

The first line contains integers NN and KK. Each of the next KK lines contains (a1,b1)…(aK,bK)(a1,b1)…(aK,bK) (1≤ai<bi≤N1≤ai<bi≤N).

OUTPUT FORMAT (print output to the terminal / stdout):

Print NN lines of output, where the iith line contains the number of unique positions that cow ii reaches.

SAMPLE INPUT:

5 4
1 3
1 2
2 3
2 4

SAMPLE OUTPUT:

4
4
3
4
1

  • Cow 11 reaches positions {1,2,3,4}{1,2,3,4}.
  • Cow 22 reaches positions {1,2,3,4}{1,2,3,4}.
  • Cow 33 reaches positions {1,2,3}{1,2,3}.
  • Cow 44 reaches positions {1,2,3,4}{1,2,3,4}.
  • Cow 55 never moves, so she never leaves position 55.

SCORING:

  • Test cases 1-5 satisfy N≤100,K≤200N≤100,K≤200.
  • Test cases 6-10 satisfy N≤2000,K≤4000N≤2000,K≤4000.
  • Test cases 11-20 satisfy no additional constraints.

解题思路

        我们声称同一周期中所有奶牛的答案都是相同的。因为每进行 K 次交换,一切都会重复,如果两头奶牛在 K 次交换后一直处于同一位置,那么它们最终会到达相同的位置。 K 次交换后,牛 i 到位置 pi,所以牛 i 和牛 pi 的答案是一样的。这个逻辑扩展到循环中的每一头奶牛(奶牛 pi 的答案等于奶牛 pi 等等)。

#include <bits/stdc++.h>
using namespace std;

int N,K;
int A[200001],B[200001]; //input
int P[100001]; //as described in analysis
vector<int>S[100001]; //as described in analysis
int from[100001]; //from[i] = where the cow in position i originated from
int cnt[100001]; //array to keep track of uniquePos
int uniquePos; //# of unique reachable positions

//add in S_node
void add(int node){
  for (int x:S[node]){
    if (cnt[x]==0)
      uniquePos++;
    cnt[x]++;
  }
}

//remove S_node
void remove(int node){
  for (int x:S[node]){
    if (cnt[x]==1)
      uniquePos--;
    cnt[x]--;
  }
}

bool vis[100001];
queue<int>q; //stores all nodes in current cycle

void dfs(int node){
  vis[node]=true;
  add(node);
  q.push(node);
  if (!vis[P[node]])
    dfs(P[node]);
}

int main(){
  cin>>N>>K;
  for (int i=0;i<K;i++)
    cin>>A[i]>>B[i];
  //initialize from and S
  for (int i=1;i<=N;i++){
    from[i]=i;
    S[i].push_back(i);
  }
  //simulate the first K swaps, keeping track of where each position can reach
  for (int i=0;i<K;i++){
    S[from[A[i]]].push_back(B[i]);
    S[from[B[i]]].push_back(A[i]);
    swap(from[A[i]],from[B[i]]);
  }
  //compute array P after first K swaps
  for (int i=1;i<=N;i++)
    P[from[i]]=i;
  int ans[100001];
  //run a DFS on each cycle
  for (int i=1;i<=N;i++)
    if (!vis[i]){
      dfs(i);
      int tempAns=uniquePos; //the answer 
      //assign the answer for all nodes in the cycle, which we've stored in this queue
      while (!q.empty()){
	remove(q.front());
	ans[q.front()]=tempAns;
	q.pop();
      }
    }
  for (int i=1;i<=N;i++)
    cout<<ans[i]<<endl;
  return 0;
}

Problem 2. No Time to Paint

Bessie has recently received a painting set, and she wants to paint the long fence at one end of her pasture. The fence consists of NN consecutive 1-meter segments (1≤N≤1051≤N≤105). Bessie has 26 different colors available, which she labels with the letters 'A' through 'Z' in increasing order of darkness ('A' is a very light color, and 'Z' is very dark). She can therefore describe the desired color she wants to paint each fence segment as a length-NN string where each character is a letter.

Initially, all fence segments are uncolored. Bessie can color any contiguous range of segments with a single color in a single brush stroke as long as she never paints a lighter color over a darker color (she can only paint darker colors over lighter colors).

For example, an initially uncolored segment of length four can be colored as follows:

.... -> BBB. -> BBLL -> BQQL

Running short on time, Bessie thinks she may need to leave some consecutive range of fence segments unpainted! Currently, she is considering QQ candidate ranges (1≤Q≤1051≤Q≤105), each described by by two integers (a,b)(a,b) with 1≤a≤b≤N1≤a≤b≤N giving the indices of endpoints of the range a…ba…b of segments to be left unpainted.

For each candidate range, what is the minimum number of strokes needed to paint every fence segment outside those in the range with its desired color while leaving all fence segments inside the range uncolored? Note that Bessie does not actually do any painting during this process, so the answers for each candidate range are independent.

INPUT FORMAT (input arrives from the terminal / stdin):

The first line contains NN and QQ.

The next line contains a string of length NN characters representing the desired color for each fence segment.

The next QQ lines each contain two space-separated integers aa and bb representing a candidate range to possibly leave unpainted.

OUTPUT FORMAT (print output to the terminal / stdout):

For each of the QQ candidates, output the answer on a new line.

SAMPLE INPUT:

8 2
ABBAABCB
3 6
1 4

SAMPLE OUTPUT:

4
3

In this example, excluding the sub-range corresponding to the desired pattern 𝙱𝙰𝙰𝙱BAAB requires four strokes to paint while excluding 𝙰𝙱𝙱𝙰ABBA requires only three.

.... -> AA.. -> ABBB -> ABCB

SCORING:

  • Test cases 1-4 satisfy N,Q≤100N,Q≤100.
  • Test cases 5-7 satisfy N,Q≤5000N,Q≤5000.
  • Test cases 8-13 satisfy no additional constraints.

解题思路

        对于一个候选范围(a,b),只需独立计算长度为a-1的前缀和长度为N-b的后缀的最小笔画数,并将它们相加即可。现在让我们描述如何计算每个前缀的最小笔画数(后缀的计算方式类似)。最简单的方法是从左到右扫描输入,同时保持一堆“活动笔触”。每次我们看到比堆栈顶部的颜色更高的颜色时,我们将其推入堆栈(因此堆栈将包含从底部到顶部的升序颜色)。每次我们看到颜色 c 时,我们都会从堆栈中弹出所有大于 c 的颜色,因为这些画笔笔触需要结束才能使颜色 c 可见。压入堆栈的总数告诉我们每个前缀所需的笔触数。 

#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
const int MAX_N = 100000;
  
string S;
int N, prefix_sol[MAX_N+1], suffix_sol[MAX_N+1];
    
void build_sol(int *sol)
{
  stack<char> active_colors;
  for (int i=0; i<N; i++) {
    sol[i+1] = sol[i];
    while (!active_colors.empty() && active_colors.top() > S[i]) active_colors.pop();
    if (active_colors.empty() || active_colors.top() < S[i]) { active_colors.push(S[i]); sol[i+1]++; }
  }
}
     
int main(void)
{
  int Q, i, j;
  cin >> N >> Q >> S;
  build_sol(prefix_sol);
  reverse (S.begin(), S.end());
  build_sol(suffix_sol);  
  for (int q=0; q<Q; q++) {
    cin >> i >> j;
    cout << prefix_sol[i-1] + suffix_sol[N-j] << "\n";
  }
}

Problem 3. Spaced Out

Farmer John wants to take a picture of his cows grazing in their pasture to hang on his wall. The pasture is represented by an NN by NN grid of square cells (picture an N×NN×N chess board), with 2≤N≤10002≤N≤1000. In the last picture Farmer John took, his cows were too clumped together in one region of the pasture. This time around, he wants to make sure his cows are properly spaced out across the pasture. He therefore insists on the following rules:

  • No two cows may be placed in the same cell.
  • Every sub-grid of 2×22×2 cells ((N−1)×(N−1)(N−1)×(N−1) of them in total) must contain exactly 2 cows.

For example, this placement is valid:

CCC
...
CCC

while this placement is not, because the 2×22×2 square region that contains the bottom-right corner cell contains only 1 cow:

C.C
.C.
C..

There are no other restrictions. You may assume that Farmer John has an infinite number of cows available (based on previous experience, this assumption certainly seems to be true...).

Farmer John wants some cells to contain cows more than other cells. In particular, he believes that when a cow is placed in cell (i,j)(i,j), the beauty of the picture is increased by aijaij (0≤aij≤10000≤aij≤1000) units.

Determine the maximum possible total beauty of a valid placement of cows.

INPUT FORMAT (input arrives from the terminal / stdin):

The first line contains NN. The next NN lines contain NN integers each. The jjth integer of the iith line from the top is the value of aijaij.

OUTPUT FORMAT (print output to the terminal / stdout):

Print one integer giving the maximum possible beauty of the resulting photo.

SAMPLE INPUT:

4
3 3 1 1
1 1 3 1
3 3 1 1
1 1 3 3

SAMPLE OUTPUT:

22

In this sample, the maximum beauty can be achieved with the following placement:

CC..
..CC
CC..
..CC

The beauty of this placement is 3+3+3+1+3+3+3+3=223+3+3+1+3+3+3+3=22.

SCORING:

  • Test cases 2-4 satisfy N≤4N≤4.
  • Test cases 5-10 satisfy N≤10N≤10.
  • Test cases 11-20 satisfy N≤1000N≤1000

解题思路

为了解决这个问题,我们只考虑两种情况(行交替或列交替),并为每一行/列选择导致最大美感的排列(只有两个,因为它必须交替)。对于部分信用,我们可以迭代所有可能的奶牛排列(总共 2N+1−2 个)。

#include <iostream>
 
#define ll long long
 
using namespace std;
 
ll grid[1000][1000];
 
int main() {
    int n;
    cin >> n;
    for (int y = 0; y < n; y++) {
        for (int x = 0; x < n; x++) {
            cin >> grid[y][x];
        }
    }
    ll horizontalAnswer = 0;
    for (int y = 0; y < n; y++) {
        ll sums[2];
        sums[0] = 0;
        sums[1] = 0;
        for (int x = 0; x < n; x++) {
            sums[x % 2] += grid[y][x];
        }
        horizontalAnswer += max(sums[0], sums[1]);
    }
    ll verticalAnswer = 0;
    for (int x = 0; x < n; x++) {
        ll sums[2];
        sums[0] = 0;
        sums[1] = 0;
        for (int y = 0; y < n; y++) {
            sums[y % 2] += grid[y][x];
        }
        verticalAnswer += max(sums[0], sums[1]);
    }
    cout << max(horizontalAnswer, verticalAnswer) << "\n";
    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值