極小値を検索するCodeforces(インタラクティブな質問)

極小値の検索

これはインタラクティブな問題です。

ホーマーはアレイが大好きで、あなたとゲームをしたいと思っています。

ホーマーはあなたから順列a1、a2、…、整数1からnまでを隠しました。極小値であるインデックスk(1≤k≤n)を見つけるように求められます。

アレイのための12、...、nは、インデックスi(1≤i≤n)があると言われている極小場合I <分間{ I-1 I + 1 }、ここで0 = a n + 1 = +∞。配列に1からnまでのすべての整数が1回だけ含まれている場合、配列は1からnまでの整数の順列であると言われます。

最初は、この順列に関する他の情報なしで、nの値のみが与えられます。

インタラクティブな各ステップで、任意のi(1≤i≤n)を選択し、それを使用してクエリを実行できます。応答として、aiの値が与えられます。

最大100回のクエリの後、極小値であるインデックスkを見つけるように求められます

インタラクション

あなたは、整数n(1≤n≤10読み取ることによって対話を開始する5を別々の行に)。

インデックスi(1≤i≤n)でクエリを実行するには、「?別の行に「i」。次に、別の行でaiの値を読み取ります。「?」の数 クエリは100以内に制限されています。

極小値であるインデックスk(1≤k≤n)を見つけたら、「!k」を別の行に入力して、プログラムを終了します。

クエリ形式が無効な場合、または100を超える「?」を作成した場合 クエリを実行すると、間違った回答の評決が表示されます。

クエリを出力した後、行末を出力して出力をフラッシュすることを忘れないでください。そうしないと、アイドル状態の制限を超えてしまいますこれを行うには、次を使用します。

  • C ++のfflush(stdout)またはcout.flush()。
  • JavaのSystem.out.flush();
  • Pascalのflush(output);
  • Pythonのstdout.flush();
  • 他の言語のドキュメントを参照してください。

ハックフォーマット

ハッキングの最初の行は、単一の整数n(1≤n≤10含むべきである5)。

2行目は、N個の別個の整数含むべきである12、...、N(1≤a I ≤n)。

入力

5
3
2
1
4
5

出力

1
2
3
4
5
3

注意

この例では、最初の行に整数5が含まれており、配列の長さがn = 5であることを示しています。

この例では、5つの「?」を作成します クエリを実行すると、配列はa = [3,2,1,4,5]であり、k = 3は極小値であると結論付けられます。

一般的なアイデア

1からnまでのすべての順列を格納する長さnの配列があります。100以下のクエリで極小値を見つける必要があります。最初は、配列のサイズのみがわかります。配列の各位置の値は、

分析

3点で最小値を見つけ、間隔を[l、r]、mid =(l + r)>> 1に設定します。a[mid + 1]> a [mid]の場合、最小値は左側でなければなりません。ミッド+1側(mid + 1を除く)の場合、最小値はミッドの右側(ミッドを除く)である必要があります。配列a []は1〜nの完全な配列を格納するため、a [mid]が存在する必要があります。 ≠[中間+ 1]、時間複雑性O(ログ(N))
分析によって、総クエリの最大数は2⌈logある2質問の要件を満たしてn⌉≤34<100、

ACコード

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

const int N=1e5+10;
int a[N];

int main()
{
    
    
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int n;
	cin>>n;
	int l=1,r=n;
	while(l<r)
	{
    
    
		int mid=(l+r)>>1;
		cout<<"? "<<mid<<endl;
		cin>>a[mid];
		cout<<"? "<<mid+1<<endl;
		cin>>a[mid+1];
		if(a[mid+1]>a[mid]) r=mid;
		else l=mid+1;
	}
	cout<<"! "<<l<<endl;
	
	return 0;
}

問題解決コード

#include <bits/stdc++.h>
 
using namespace std;
 
const int MAXN = 100010;
 
int n;
int a[MAXN];
 
int query(int x)
{
    
    
	if (1 <= x && x <= n)
	{
    
    
		printf("? %d\n", x);
		fflush(stdout);
		scanf("%d", &a[x]);
	}
}
 
int main()
{
    
    
	scanf("%d", &n);
	a[0] = a[n + 1] = n + 1;
	int L = 1, R = n;
	while (L < R)
	{
    
    
		int m = (L + R) / 2;
		query(m);
		query(m + 1);
		if (a[m] < a[m + 1])
			R = m;
		else
			L = m + 1;
	}
	printf("! %d\n", L);
	fflush(stdout);
	return 0;
}

注意

1. Codeforcesインタラクティブ問題の紹介インタラクティブ問題:参加者向けガイド
2.バッファの更新に注意してください。cout<< endlを使用すると、バッファが自動的に更新されます。printfを使用する場合は、fflush(stdout);を追加する必要があります。

おすすめ

転載: blog.csdn.net/weixin_46155777/article/details/113793342