Submission #1152499

#TimeUsernameProblemLanguageResultExecution timeMemory
1152499jmuzhenZagrade (COI20_zagrade)C++20
71 / 100
266 ms6824 KiB
// https://oj.uz/problem/view/COI20_zagrade // try to grab 'entire sequence is valid' subtasks /* let's start over. what if we just naively match brackets? so we know the sequence is valid for this subtask * and so s[0] is (. then we must have some ) matching s[0]. like ()<- or (()())<- . also, since the sequence is valid, * notice that if [0,i] matches then i is definitely ). * we can tell if [0,i] matches if query(0,i) is 1. but what if it is 0 ? Then 0,i doesn't match. this means that even though * 0,i might be ( and ) respectively, They don't match because i is matched to some other (. same as simple bracket matching. * on the other hand, if query(0,i) is 1 then 0, i "match" because i is the correct match for 0. * what does this mean? * since sequence is valid then every element must match to _SOMETHING_. it can be a starting point or an ending point. * lets fix the starting point at 0 first. then to find its match we can query every element 1,2,3,...,n until we get a 1. * then this is O(N^2) if we repeat for every element. but wait, can we repeat this for every element? say in ((())), * 0 matches with 6. then we go to 1, it matches with 5, etc. that works. but what if it's an extreme case. * say ()()(). wait that works also. * say (())(). then 0 matches with 3. * wait, why am I using 0-indexing? whatever, we will continue to use 0 indexing from now on. * say (())(). then 0 matches with 3, then go on to 1. 1 matches with 2. then go on to 4. 4 matches with 5. * so i think this works but it's O(N^2) queries. * * can we improve? * - 1. obviously every query should have an even length otherwise its always 0. * - so we can optimise this in query function itself, just return 0 if length is odd * - why is this current method O(N^2) ? oh, because we may need to traverse the entire sequence to match for each one. * say ((())), we need to go through the entire string to get the answer for 0, 1, etc. * how to improve this? * what if we copy bracket matching method. in bracket matching naively searching for a pair is also O(N^2) right. * so bracket matching uses a stack. so it's not eager to find the match for a specific starting point now, it pushes it onto * the stack and tries to find the match later. * so we shouldnt fix the starting point! * we should fix the ending point! * but how to do that? * say we have a stack, its empty at first. * OHHH! because if the stack is empty that means we are at index 0 and that means we are definitely an open bracket * that means we can just push 0 on the stack and look for a mtch later. * then when 1 comes, how do we check if its a match? * just run a query. query(0, 1) * if this is 1 then we just match them and continue on. (decomposed the problem) * if its 0 then that means 1 must be ( and we push 1 on the stack. * but wait, is this generalisable to long sequence? * but wait, at least this optimises it. because we dont need to check with 0 anymore, we can just * check with the LAST element of the stack! because of how bracket matching works. always matches the inner bracket first, * if it doesnt match inner bracket it cannot match outer bracket. so we can just skip. * i think this works. so only O(N) queries! * so if we see a element that gives a query result of 1 with the top stack element, we just match it with that, * and then pop both off the stack. * i think this works. * * * */ #include <bits/stdc++.h> using namespace std; int n, q; map<pair<int, int>, int> query_memo; // optimisation // helpers to query & output inline int query(int i, int j) { if (query_memo[{i,j}]) { return query_memo[{i, j}]; } if ((j - i + 1) % 2 == 1) { return 0; } cout << "? " << i << " " << j << endl; int r; cin >> r; return query_memo[{i,j}] = r; } inline int query(int i, int j, const vector<int>& input) { return query(input[i], input[j]); } inline void output(vector<short>&s) { cout << "! "; for (int i = 1; i <= n; i++) { cout << (s[i] == 0 ? '(' : ')'); } cout << endl; } inline void output(vector<char>&s) { cout << "! "; for (int i = 1; i <= n; i++) { cout << s[i]; } cout << endl; } int main() { cin >> n >> q; vector<char> out(n+1); stack<int> st; for (int i = 1; i <= n; i++) { if (st.empty()) { out[i] = '('; st.push(i); continue; } int p = st.top(); int res = query(p, i); if (res == 1) { // match st.pop(); out[p] = '('; out[i] = ')'; } else { // is open because otherwise, it would be a match out[i] = '('; st.push(i); } } output(out); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...