Codeforces Round #703 (Div. 2) C. Guessing the Greatest

C1. Guessing the Greatest (easy version)
C2. Guessing the Greatest (hard version)

Codeforces C question Guessing the Greatest is divided into two versions, easy and hard. The only difference is the limit on the number of inquiries. The easy version is given below.

Insert picture description here
Insert picture description here
Example

input

5

3

4

output

? 1 5

? 4 5

! 1

Insert picture description here
General idea

Given an array of length n, the elements in the array are different, each time you can query the position of the second largest number in the interval [l,r] (l<r), and find the largest number within the limited number of queries The position of the subscript.

analysis

The basic idea of ​​the two versions is dichotomy, and the hard version limits the number of inquiries less.
Let the answer range be [l,r], the midpoint is mid, and the second largest number is smax.

easy version

Ask [l,r] first, if smax<=mid, then ask [l,mid], if you ask again the position of the second largest number is still smax, it means that the interval of the largest number is [l,mid], and vice versa The interval is [mid+1,r], and smax>mid is the same. In this way, the answer interval can be reduced by half by asking twice. Through calculation, the maximum number of inquiries is 2*⌈log 2 10 5=34

hard version

First query [1,n] to determine the position smax of the second largest number, if smax>1, then query [1,smax], if the position of the second largest number does not change, the interval of the largest number is [1,smax] -1], otherwise the interval of the maximum number is [smax+1,n]. Determine the size relationship between smax and the position of the maximum value through no more than two queries, which is convenient for the next step of judgment. Take the interval of the maximum value [1,smax-1] as an example, at this time l=1,r=smax-1, and the midpoint is mid. Every time you ask [mid,smax], if the position of the second largest number is still It is smax, which means that the maximum number is in [mid,smax-1], just let l=mid, otherwise r=mid-1, and the maximum value is in the interval [smax+1,n]. The situation is similar. Through calculation, the maximum number of queries in this method is 2+⌈log 2 10 5=19

AC code

easy version

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

typedef long long ll;

int ask(int l,int r)
{
    
    
	if(l>=r) return 0;
	int x;
	cout<<"? "<<l<<" "<<r<<endl;
	cin>>x;
	return x;
}

int main()
{
    
    
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
	cin>>n;
	int l=1,r=n;
	int x,y;
	while(l<r)
	{
    
    
		if(r-l==1)
		{
    
    
			x=ask(l,r);
			if(x==l) l=r;
			break;
		}
		int mid=(l+r)>>1;
		x=ask(l,r);
		if(x<=mid)
		{
    
    
			y=ask(l,mid);
			if(y==x) r=mid;
			else l=mid+1;
		}
		else
		{
    
    
			y=ask(mid+1,r);
			if(y==x) l=mid+1;
			else r=mid;
		}
	}
	cout<<"! "<<l<<endl;
	
	return 0;
}

hard version

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

typedef long long ll;

int ask(int l,int r)
{
    
    
	int num;
	cout<<"? "<<l<<" "<<r<<endl;
	cin>>num;
	return num;
}

int main()
{
    
    
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
	cin>>n;
	int x,y;
	int l,r;
	x=ask(1,n);
	if(x!=1) y=ask(1,x);
	if(y!=x||x==1)
	{
    
    
		l=x+1,r=n;
		while(l<r)
		{
    
    
			int mid=(l+r)>>1;
			if(ask(x,mid)!=x) l=mid+1;
			else r=mid;
		}
	}
	else
	{
    
    
		l=1,r=x-1;
		while(l<r)
		{
    
    
			int mid=(l+r+1)>>1;
			if(ask(mid,x)!=x) r=mid-1;
			else l=mid;
		}
	}
	cout<<"! "<<l<<endl;
	
	return 0;
}

note

1. In the easy version, if rl==1, [l,r] is already the minimum interval that can be inquired, and the position of the maximum value can be determined by only one inquiry. This situation is judged separately
2. In the hard version , The value of mid in the two cases is different, mid=(l+r)>>1 or mid=(l+r+1)>>1 is related to the value of l, r in the interval dichotomy

Guess you like

Origin blog.csdn.net/weixin_46155777/article/details/113919089
Recommended