Блог пользователя xiaowuc1

Автор xiaowuc1, 5 лет назад, По-английски

Hi all,

The final contest of the 2021-2022 USACO season will be running this weekend. Good luck to everyone! Please wait until the contest is over for everyone before discussing anything contest-related (including but not limited to your scores or anything about the problems).

  • Проголосовать: нравится
  • +61
  • Проголосовать: не нравится

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +27 Проголосовать: не нравится

I always fully solve exactly (but no more than) one problem each USACO contest (trend is ongoing for last 6 contests, I think).

Good luck!

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

How to solve Silver 2nd problem?

»
5 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

How to solve Silver P3?

  • »
    »
    5 лет назад, скрыть # ^ |
    ← Rev. 5  
    Проголосовать: нравится 0 Проголосовать: не нравится

    If you can change any letter to the other two letters, that means that those two letters = the first letter (WO = C, WC = O, CO = W). Same letter pairs can be ignored, so you skip them or use another letter to represent a "void" and then take it into account when joining letters(so you won't join a letter with a void). So the brute-force approach would be to divide the length of the string by two each time, by transforming two letters into one until there's only one letter left, if it's C then answer is YES, if not then answer is NO. That would pass for tests 1-5 or something like that.

    The same approach could be optimized by using data structures as segment tree (and probably sparse table too).

    That approach is the one I used, but I've got the feeling that there's probably a better one, if anyone has another approach pls comment it down :)

    UPD: From a comment that I've seen down below, the order of operations doesn't matter so you can just keep joining letters and there's no need of data structures. Now I feel dumb lol :(

  • »
    »
    5 лет назад, скрыть # ^ |
    ← Rev. 2  
    Проголосовать: нравится +1 Проголосовать: не нравится

    If you notice the operation between two characters in the string was nothing but the XOR of them. Since C(1) ≡ O(2)W(3) , CC ≡ ""(0) , also the order of operation doesn't matter here , so we can just check if XOR of S[L..R] == 1(C) or not.

  • »
    »
    5 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    For any two adjacent letters, we can always swap them using some operations:

    XY -> XZX -> YX

    (where X, Y, Z are letters among C, O, W)

    so the order of the string doesn't matter because we can always arrange it in the order: "CC..C OO...O WW...W" What matters is the number of C's and O's and W's. Since the same adjacent letters can be deleted, all we need to consider is the parity of the number of C's and O's, and W's, and this quantity can be easily computed using prefix sum for each query.

    For each query, there are 8 cases: C, O, W, CO, CW, OW, COW, and void. (order in each string doesn't matter)

    CO is equivalent to W

    CW is equivalent to O

    OW is equivalent to C

    COW -> WW -> void

    We also need to ensure that C, O, W, and void each can't reach other letters. My proof is below:

    During each operation, the parity of the number of C and O doesn't change, because the ways to lose and gain O or C are OO -> void, CC -> void, OC -> W, OW -> C, CW -> O. We can see that the parity doesn't change. same for O and W, and W and C. We don't need to worry too much about void because there is no reverse operation of it. Knowing these, we'll prove the statement by contradiction:

    If C can reach W in some operations, the parity of the number of C and O in C is 1, but the parity of the number of C and O in W is 0, which contradicts what we proved above, and the same proof for C O and W O.

    My C++ code below:

    #include <bits/stdc++.h>
    using namespace std;
    int pre[(int)2e5+1][3];
    int main(){
    	string s; int q;
    	cin>>s>>q;
    	for(int i=1;i<=s.length();i++){
    		pre[i][0]=pre[i-1][0];
    		pre[i][1]=pre[i-1][1];
    		pre[i][2]=pre[i-1][2];
    		if(s[i-1]=='C') pre[i][0]++;
    		else if(s[i-1]=='O') pre[i][1]++;
    		else pre[i][2]++;
    	}
    	while(q--){
    		int l,r; cin>>l>>r;
    		bool c=(pre[r][0]-pre[l-1][0])%2;
    		bool o=(pre[r][1]-pre[l-1][1])%2;
    		bool w=(pre[r][2]-pre[l-1][2])%2;
    		if(w&&o&&c||!w&&o&&c||w&&!o&&c||!w&&o&&!c||w&&!o&&!c||!w&&!o&&!c) cout<<"N";
    		else cout<<"Y";
    	}
    }
    
    

    We can answer each query in O(1) with O(n) pre-computation.

    I hope this helps you.

»
5 лет назад, скрыть # |
 
Проголосовать: нравится +10 Проголосовать: не нравится

Any ideas how to solve plat P1 or P2?

  • »
    »
    5 лет назад, скрыть # ^ |
    ← Rev. 4  
    Проголосовать: нравится +16 Проголосовать: не нравится

    P2 :

    First , you need to calculate the scc of the graph. (If one scc has only one vertex , then it is impossible to win ).

    Second , if there is a vertex whose out degree is 1 , then merge the vertex and the vertex it can go to .

    Keep doing the second step until every vertex's out degree is not equal to 1.

    Each query is to check whether u,v is the same vertex.

    solution
»
5 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Results are out at http://usaco.org/index.php?page=open22results

Personally, I qualified for gold with an 833 :)