USACO February 2021-2022 February Contest Silver Group Question Answers

Those who want to prepare USAco can refer to this article!

If you want to get good at USACO—read this article is enough

Problem 1. Redistributing Gifts

Farmer John has N gifts labeled 1…N for his N cows, also labeled 1…N(1≤N≤500). Each cow has a wishlist, which is a permutation of all N gifts such that the cow prefers gifts that appear earlier in the list over gifts that appear later in the list.

FJ was lazy and just assigned gift i to cow i for all i. Now, the cows have gathered amongst themselves and decided to reassign the gifts such that after reassignment, every cow ends up with the same gift as she did originally, or a gift that she prefers over the one she was originally assigned.

For each i from 1 to N, compute the most preferred gift cow i could hope to receive after reassignment.

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

The first line contains N. The next N lines each contain the preference list of a cow. It is guaranteed that each line forms a permutation of 1…N.

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

Please output NN lines, the ii-th of which contains the most preferred gift cow ii could hope to receive after reassignment.

SAMPLE INPUT:

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

SAMPLE OUTPUT:

1
3
2
4

In this example, there are two possible reassignments:

  • The original assignment: cow 1 receives gift 11, cow 22 receives gift 22, cow 33 receives gift 33, and cow 44 receives gift 44.
  • Cow 11 receives gift 11, cow 22 receives gift 33, cow 33 receives gift 22, and cow 44 receives gift 44.

Observe that both cows 11 and 44 cannot hope to receive better gifts than they were originally assigned. However, both cows 22 and 33 can.

SCORING:

  • Test cases 2-3 satisfy N≤8N≤8.
  • Test cases 4-11 satisfy no additional constraints.

        The distribution only if cow i receives cow j corresponds to partitioning the vertices of G into a number of simple cycles containing edges i→j. It follows that one of the simple cycles contains the edge i→j. If there exists a simple cycle C containing i→j. We can then assign each cow on C a gift to the next cow in the cycle, and every cow on C will end up better off. Let all cows not along the line of C receive their original gifts. This corresponds to the efficient distribution.

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

int N;
bitset<501> reachable[501];
vector<int> gifts[501];

void dfs(int src, int cur) {
	if (reachable[src][cur])
		return;
	reachable[src][cur] = true;
	for (int g : gifts[cur])
		dfs(src, g);
}

void calc_reachable_dfs() {
	for (int i = 1; i <= N; ++i)
		dfs(i, i);
}

void calc_reachable_floyd() {
	for (int i = 1; i <= N; ++i)
		for (int g : gifts[i])
			reachable[i][g] = true;
	for (int k = 1; k <= N; ++k) // run floyd-warshall
		for (int i = 1; i <= N; ++i)
			if (reachable[i][k])
				reachable[i] |= reachable[k];
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> N;
	assert(N <= 500);
	for (int i = 1; i <= N; ++i) {
		gifts[i].resize(N);
		for (int &g : gifts[i])
			cin >> g;
		while (gifts[i].back() != i)
			gifts[i].pop_back();
	}
 
	calc_reachable_dfs(); 

	for (int i = 1; i <= N; ++i)
		for (int g : gifts[i])
			if (reachable[g][i]) {
				cout << g << "\n";
				break;
			}
}

Problem 2. Robot Instructions

Bessie is learning how to control a robot she has recently received as a gift.

The robot begins at point (0,0)(0,0) on the coordinate plane and Bessie wants the robot to end at point (xg,yg)(xg,yg). Bessie initially has a list of NN (1≤N≤401≤N≤40) instructions to give to the robot, the ii-th of which will move the robot xixi units right and yiyi units up (or left or down when xixi and yiyi are negative, respectively).

For each KK from 11 to NN, help Bessie count the number of ways she can select KK instructions from the original NN such that after the KK instructions are executed, the robot will end at point (xg,yg)(xg,yg).

**Note: the time and memory limits for this problem are 4s and 512MB, twice the defaults.**

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

The first line contains NN. The next line contains xgxg and ygyg, each in the range −109…109−109…109. The final NN lines describe the instructions. Each line has two integers xixi and yiyi, also in the range −109…109−109…109.

It is guaranteed that (xg,yg)≠(0,0)(xg,yg)≠(0,0) and (xi,yi)≠(0,0)(xi,yi)≠(0,0) for all ii.

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

Print NN lines, the number of ways Bessie can select KK instructions from the original NN for each KK from 11 to NN.

SAMPLE INPUT:

7
5 10
-2 0
3 0
4 0
5 0
0 10
0 -10
0 10

SAMPLE OUTPUT:

0
2
0
3
0
1
0

In this example, there are six ways Bessie can select the instructions:

(-2,0) (3,0) (4,0) (0,10) (0,-10) (0,10) (1 2 3 5 6 7)
(-2,0) (3,0) (4,0) (0,10) (1 2 3 5)
(-2,0) (3,0) (4,0) (0,10) (1 2 3 7)
(5,0) (0,10) (0,-10) (0,10) (4 5 6 7)
(5,0) (0,10) (4 5)
(5,0) (0,10) (4 7)

For the first way, the robot's path looks as follows:

(0,0) -> (-2,0) -> (1,0) -> (5,0) -> (5,10) -> (5,0) -> (5,10)

SCORING:

  • Test cases 2-4 satisfy N≤20N≤20.
  • Test cases 5-16 satisfy no additional constraints.

        The first observation we make in this problem is that the order in which operations occur does not matter, what matters is which operations we perform. This means that 2N different sets of operations need to be considered. To solve subtasks, we can manually consider each set. Below is the code, which solves subtasks with N≤20. We note that the problem's original bound N ≤ 40, is only twice as large. This suggests splitting a given operation into two halves of approximately equal size, and running the above algorithm on the two halves. If we iterate over one of the given lists, we know exactly how far we need to move from the other half of the instruction.

#include <bits/stdc++.h>

using namespace std;

using P = pair<long long, long long>;
P operator+(P a, P b) { return {a.first + b.first, a.second + b.second}; }
P operator-(P a, P b) { return {a.first - b.first, a.second - b.second}; }

vector<pair<P, int>> all_subsets(const vector<P> &dirs) {
	vector<pair<P, int>> v{
   
   {}};
	for (const P &d : dirs) {
		v.resize(2 * v.size());
		for (int i = 0; i < v.size() / 2; i++) {
			v[i + v.size() / 2] = {v[i].first + d, v[i].second + 1};
		}
	}
	sort(v.begin(), v.end());
	return v;
}

int main() {
	int N;
	cin >> N;
	P goal;
	cin >> goal.first >> goal.second;
	vector<P> dirs(N);
	for (auto &d : dirs) {
		cin >> d.first >> d.second;
	}
	vector<pair<P, int>> a =
		all_subsets(vector<P>(begin(dirs), begin(dirs) + N / 2));
	vector<pair<P, int>> b =
		all_subsets(vector<P>(begin(dirs) + N / 2, end(dirs)));
	reverse(b.begin(), b.end());
	vector<long long> ans(N + 1);
	vector<int> with_num;
	P rest_prev{1e18, 1e18};
	int ib = 0;
	for (const auto &[offset, num] : a) {
		const P rest = goal - offset;
		if (rest != rest_prev) {
			rest_prev = rest;
			with_num = vector<int>(N - N / 2 + 1);
			for (; ib < b.size() && b.at(ib).first > rest; ++ib);
			for (; ib < b.size() && b.at(ib).first == rest; ++ib) {
				++with_num.at(b.at(ib).second);
			}
		}
		for (int i = 0; i < with_num.size(); i++) {
			ans[i + num] += with_num[i];
		}
	}
	for (int i = 1; i <= N; i++) {
		cout << ans[i] << "\n";
	}
}

Problem 3. Email Filing

Farmer John has fallen behind on organizing his inbox. The way his screen is organized, there is a vertical list of folders on the left side of the screen and a vertical list of emails on the right side of the screen. There are MM total folders, numbered 1…M1…M (1≤M≤104)1≤M≤104). His inbox currently contains NN emails numbered 1…N1…N (1≤N≤1051≤N≤105); the iith email needs to be filed into folder fifi (1≤fi≤M1≤fi≤M).

FJ's screen is rather small, so he can only view KK (1≤K≤min(N,M)1≤K≤min(N,M)) folders and KK emails at once. Initially, his screen starts out displaying folders 1…K1…K on the left and emails 1…K1…K on the right. To access other folders and emails, he needs to scroll through these respective lists. For example, if he scrolls down one position in the list of folders, his screen will display folders 2…K+12…K+1, and then scrolling down one position further it will display folders 3…K+23…K+2. When FJ drags an email into a folder, the email disappears from the email list, and the emails after the one that disappeared shift up by one position. For example, if emails 1,2,3,4,51,2,3,4,5 are currently displayed and FJ drags email 3 into its appropriate folder, the email list will now show emails 1,2,4,5,61,2,4,5,6. FJ can only drag an email into the folder to which it needs to be filed.

Unfortunately, the scroll wheel on FJ's mouse is broken, and he can only scroll downwards, not upwards. The only way he can achieve some semblance of upward scrolling is if he is viewing the last set of KK emails in his email list, and he files one of these. In this case, the email list will again show the last KK emails that haven't yet been filed, effectively scrolling the top email up by one. If there are fewer than KK emails remaining, then all of them will be displayed.

Please help FJ determine if it is possible to file all of his emails.

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

The first line of input contains TT (1≤T≤101≤T≤10), the number of subcases in this input, all of which must be solved correctly to solve the input case. The TT subcases then follow. For each subcase, the first line of input contains MM, NN, and KK. The next line contains f1…fNf1…fN.

It is guaranteed that the sum of MM over all subcases does not exceed 104104, and that the sum of NN over all subcases does not exceed 105105.

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

Output TT lines, each one either containing either YES or NO, specifying whether FJ can successfully file all his emails in each of the TT subcases.

SAMPLE INPUT:

6
5 5 1
1 2 3 4 5
5 5 1
1 2 3 5 4
5 5 1
1 2 4 5 3
5 5 2
1 2 4 5 3
3 10 2
1 3 2 1 3 2 1 3 2 1
3 10 1
1 3 2 1 3 2 1 3 2 1

SAMPLE OUTPUT:

YES
YES
NO
YES
YES
NO

SCORING:

  • In inputs 2-10, the sum of MM over all subcases does not exceed 103103.
  • In inputs 11-12, no additional constraints.

        We'll iterate through the folders in order, keeping track of the topmost folder. We'll also iterate through the emails in order until we reach the last email that needs to be filed for a given topmost folder. If showing that email on the screen would cause the window to overflow, we have to mark the topmost email as skipped. Afterwards, if we can archive email, we should do so immediately. Otherwise, it's in the window. If we've iterated through all emails, we also have to simulate the behavior of scrolling up emails we skipped before.

#include <bits/stdc++.h>
 
using namespace std;
 
void rsolve() {
  int nfolder, nemail, windowsz;
  cin >> nfolder >> nemail >> windowsz;
  vector<int> emailtofolder(nemail);
  vector<vector<int>> foldertoemail(nfolder);
  vector<vector<int>> filetiming(nfolder);
  vector<bool> filed(nemail);
  vector<bool> skipped(nemail);
  vector<bool> inwindow(nemail);
  for(int i = 0; i < nemail; i++) {
    cin >> emailtofolder[i];
    filetiming[max(0, --emailtofolder[i] - windowsz + 1)].push_back(i);
    foldertoemail[emailtofolder[i]].push_back(i);
  }
  int currentemail = 0;
  int lhsemail = 0;
  int numinwindow = 0;
  int rhsemail = nemail-1;
  auto fileemail = [&](int id) -> void {
    if(inwindow[id]) {
      inwindow[id] = false;
      numinwindow--;
    }
    assert(!filed[id]);
    filed[id] = true;
  };
  int bottom = 0;
  for(int i = 0; i < nfolder; i++) {
    // file anything that can be newly filed
    if(i > bottom && i + windowsz <= nfolder) bottom++;
    for(int out: filetiming[i]) if(inwindow[out]) fileemail(out);
    while(foldertoemail[i].size() && currentemail <= foldertoemail[i].back()) {
      // the window is full so in order to consider this email, we must scroll past the current one
      if(numinwindow == windowsz) {
        while(!inwindow[lhsemail]) lhsemail++;
        skipped[lhsemail] = true;
        inwindow[lhsemail] = false;
        numinwindow--;
      }
      if(emailtofolder[currentemail] >= i && emailtofolder[currentemail] <= i + windowsz - 1) {
        // can file
        filed[currentemail++] = true;
        continue;
      }
      inwindow[currentemail++] = true; numinwindow++;
    }
    // scroll through emails that would be implicitly loaded
    while(currentemail < nemail && numinwindow < windowsz) {
      if(emailtofolder[currentemail] >= i && emailtofolder[currentemail] <= i + windowsz - 1) {
        // can file
        filed[currentemail++] = true;
        continue;
      }
      inwindow[currentemail++] = true; numinwindow++;
    }
    // scroll up emails since we've hit the end
    if(currentemail == nemail) {
      while(numinwindow < windowsz) {
        if(rhsemail < 0) break;
        if(!skipped[rhsemail]) {
          rhsemail--;
          continue;
        }
        if(emailtofolder[rhsemail] < bottom) {
          cout << "NO\n";
          return;
        }
        if(emailtofolder[rhsemail] <= bottom + windowsz - 1) {
          filed[rhsemail--] = true;
          continue;
        }
        inwindow[rhsemail--] = true; numinwindow++;
      }
    }
  }
  for(auto out: filed) {
    if(!out) {
      cout << "NO\n";
      return;
    }
  }
  cout << "YES\n";
}
 
void solve() {
  int t;
  cin >> t;
  while(t--) rsolve();
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  solve();
}

Guess you like

Origin blog.csdn.net/GeekAlice/article/details/128172798