Official

C - Count Close Pairs Editorial by en_translator


This problem can be solved with the sliding window technique.

The fundamental idea is to, for each point \(1,2,\ldots,N\), find the maximum \(M_i\) with \(i\leq M_i\leq N\) such that the distance from point \(i\) to point \(M_i\) is at most \(1\). The answer is \( (M_1-1)+(M_2-2)+\cdots+(M_N-N)\).

The important point is that \(M_1\leq M_2\leq \cdots \leq M_N\).
This is because when the distance from point \(i\) to points \(i+1,i+2,\ldots,M_i\) are all \(1\) or less, then the distance from point \((i+1)\) to points \(i+2, i+3,\ldots,M_i\) are all \(1\) or less.
Using this property, one can determine the value of \(M_i\) in the order of \(i=1,2,\ldots,N\) to reduce the number of questions by avoiding asking about pairs whose distance are already known to be \(1\) or less.

Specifically, we start from \(L=1,R=2\) and repeat the following operation:

  • Ask if the distance between point \(L\) and point \(R\) is at most \(1\). Here, if \(L=R\), do not ask a question, but advance to the next step where the distance between points \(L\) and \(R\) is at most \(1\).
  • If the distance between points \(L\) and \(R\) is at most \(1\), increase \(R\) by one, and advance to the next step. If it makes \(R>N\), determine \(M_L=M_{L+1}=\cdots=M_N=N\) and terminate the procedure.
  • If the distance between points \(L\) and \(R\) is greater than \(1\), determine \(M_L=R-1\), and increase \(L\) by one. Here, by the fact mentioned above, note that the distances from the new point \(L\) to points \(L+1,\ldots,R-1\) are all \(1\) or below.

Here, \(L\) and \(R\) increases monotonically, or always \(L\leq R\). In one operation, \(L+R\) always increases by one, and once \(R>N\) the procedure terminates, so the loop iterates at most \((2N+1)-3=2N-2\) times. (In fact, one can prove that the number of queries is at most \((2N-3)\).)

Since you are allowed to ask a query to the judge system at most \(2N\) times, this satisfies the condition. The answer can be found in \(O(N)\) time based on \(M_1,M_2,\ldots,M_N\) obtained. Hence, the problem has been solved.

Sample code in C++:

#include <bits/stdc++.h>

using namespace std;

int main() {
	int n;

	cin>>n;

	int l=1,r=2,ans=0;
	string s;

	while(r<=n){
		cout<<"? "<<l<<" "<<r<<endl;
		cin>>s;
		if(s=="Yes"){
			r++;
		}
		else{
			ans+=(r-l-1);
			l++;
			if(l==r)r++;
		}
	}
	while(l<n){
		ans+=(r-l-1);
		l++;
	}
	
	cout<<"! "<<ans<<endl;
	return 0;
}

posted:
last update: