Interactive and Communication Problems
Author: Andi Qu
Some tips and tricks
In this module, we assume that "interactive" means problems that allow a limited number of queries and "communication" means problems about communicating between two separate programs.
Interactive Problems
Tip 1 - Exploit the Limits
Since almost all interactive problems have a limit on the number of queries you may ask, you should use that limit to guide your thinking. There's no point in trying to come up with a solution that uses queries when the limit is !
There are three types of interactive problems:
- Problems that directly tell you the target complexity of your solution (e.g. IOI 2014 Rail).
- Problems that only tell you the maximum number of queries you may use (e.g. IOI 2013 Cave).
- Problems that have a hidden limit on the number of queries (e.g. IOI 2015 Scales).
The first type is nice because we get an idea of what our solution should look like.
The second type is slightly less nice, but we can still approximate the target complexity (e.g. and queries).
The third type is the least nice, but fortunately, we can sometimes still figure out the hidden limit. For example, in problems with relative scoring (like IOI 2015 Scales), we can submit a solution that uses a fixed number of queries for each input and then reverse-engineer the limit from our score.
Tip 2 - Divide and Conquer
In most interactive problems, the solution is to divide and conquer. This is usually either binary search ( queries) or something like merge sort ( queries)
Whenever you see large input limits and small query limits, you should immediately think of binary search.
Focus Problem – try your best to solve this problem before continuing!
In this problem, we have and . Notice how - this suggests that we should binary search.
Indeed, that's the solution - try to come up with it yourself!
Solution
The solution is to binary search on the DFS order of the tree for the largest prefix without an easter egg. This works because any prefix of the DFS order is a connected component.
#include "grader.h"#include <bits/stdc++.h>using namespace std;vector<int> graph[513], ord;void dfs(int node = 1, int parent = 0) {ord.push_back(node);for (int i : graph[node])if (i != parent) dfs(i, node);
Problems
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
IOI | Easy | ||||
IOI | Easy | ||||
IOI | Normal | ||||
IOI | Normal | ||||
APIO | Normal | ||||
CEOI | Hard | ||||
IOI | Hard | ||||
IOI | Hard | ||||
IOI | Very Hard | ||||
IOI | Very Hard | ||||
IOI | Very Hard | ||||
APIO | Very Hard |
Communication Problems
Tip 1 - Don't Send Everything
Don't worry about not being able to send all the available information - in most cases, you shouldn't be able to!
Focus Problem – try your best to solve this problem before continuing!
In this problem, we're asked to store and compare an integer with several other integers.
Since these numbers can go up to , we can't just naively store and access (since that would take 24 operations).
Luckily, we can still store sufficient information about - just not in binary!
Solution - cmp
Here's how our algorithm works:
- Consider and in base 4
- First, encode each prefix of (6 operations)
- Next, binary search for the longest common prefix of and (3 operations)
- If this prefix is of length 6,
- Otherwise, consider the digit directly after this prefix for :
- If , then we only need to check whether is encoded
- Otherwise, we only need to check whether is encoded
- Check whether it is and return the answer (1 operation)
This algorithm uses only 10 operations instead of our original 24 - a significant improvement!
#include "cmp.h"int delta[6]{1, 4097, 5121, 5377, 5441, 5457};void remember(int n) {for (int i = 0; i < 6; i++) bit_set((n >> i * 2) + delta[i]);}int compare(int b) {int l = 0, r = 6;
Tip 2 - Brute Force
Sometimes, the amount of information that we can send is (slightly) more than the amount of information we need to decode.
In this case, we can simply map each piece of information we want to decode to a piece of information that we can send.
Focus Problem – try your best to solve this problem before continuing!
In this problem, we want to encode and decode an array of 64 integers less than 256 using an unordered sequence of 320 integers less than 256.
The number of arrays of 64 integers less than 256 is slightly less than the number of increasing sequences of 320 integers less than 256, so we can just map each array to an increasing sequence (using bignums) and send that sequence.
Tip 3 - XOR
XOR has a nice property where . This lets us solve many problems where the data sent is corrupted or the receiver doesn't know what data the sender sent.
Focus Problem – try your best to solve this problem before continuing!
Solution - Coins
Let the XOR-sum of the positions with heads-up coins be . Notice how if we flip coin , then the new XOR-sum of the positions with heads-up coins is now .
This allows Shahrnaz to determine after Arnavaz flips exactly 1 coin!
#include "coins.h"std::vector<int> coin_flips(std::vector<int> b, int c) {std::vector<int> flips(1);int xr = c;for (int i = 0; i < b.size(); i++) { xr ^= b[i] * i; }flips[0] = xr;return flips;}int find_coin(std::vector<int> b) {int xr = 0;for (int i = 0; i < b.size(); i++) { xr ^= b[i] * i; }return xr;}
Problems
Status | Source | Problem Name | Difficulty | Tags | |
---|---|---|---|---|---|
IOI | Easy | ||||
CEOI | Normal | ||||
JOI | Normal | ||||
IOI | Normal | ||||
IOI | Normal | ||||
JOI | Normal | ||||
JOI | Hard | ||||
JOI | Hard | ||||
JOI | Very Hard |
CEOI tasks can be found here.
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!