番号範囲
整数nおよびqはクエリのアレイの昇順に長さを与えられました。
クエリごとに、戻り要素kの開始位置と終了位置(0から位置カウント)。
要素が配列に存在しない場合は、「-1-1」が返されます。
入力形式
最初の行は、整数nおよびqが含まれており、配列の長さは、質問の数を表します。
2行目は、完全な配列を示す(1〜10,000の範囲の両方)nは整数を含んでいます。
次q行、各行は、整数kを含むクエリ要素を表します。
出力フォーマット
q行の合計、必要な要素の開始位置と終了位置を表す2つの整数を含む各行。
要素が配列に存在しない場合は、「-1-1」が返されます。
データ範囲
1≤n≤100000
1≤q≤10000
1≤k≤10000
アイデア:
ポイントを見つけ1.左:
-区間を[0 ,. 1-N-]
-分析条件:NUM [中間]> =タール
右点を見つける2:
-区間[左端点,. 1-N-]
-分析条件:NUM [中間] <=タール
コード:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n,q;
int num[N];
int main(void)
{
scanf("%d %d",&n,&q);
for(int i = 0;i < n;i++)
scanf("%d",&num[i]);
while(q--)
{
int tar;
scanf("%d",&tar);
//找左端点
int l = 0,r = n-1;
while(l < r)
{
int mid = l + r >> 1;
if(num[mid] >= tar)
r = mid;
else
l = mid + 1;
}
if(num[l] != tar)
printf("-1 -1\n");
else
{
printf("%d ",l);
//找右端点
r = n - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(num[mid] <= tar)
l = mid;
else
r = mid - 1;
}
printf("%d\n",l);
}
}
return 0;
}
ロボットの跳躍の問題
ロボットは、古いDOSベースのゲームをプレイしています。
左から右へ、Nに0から番号-ゲームは、N + 1つの建物があります。
0番の建物の高さは、建物の高さは、私はH(I)単位での番号、0単位です。
最初は、数のゼロにおけるロボットの建設。
すべてのステップは、次の(右側)アーキテクチャにジャンプします。
ロボット構造は、それが今エネルギー値Eであるとk番目の仮定では、次のステップk + 1番目の建物にジャンプします。
H(K + 1)> E場合は 、 その後、ロボットは、H(K + 1)-Eエネルギー値を失うことになる、それ以外の場合は、エネルギー値EHの(K + 1)を取得します。
ゲームの目的は、N番目の建物に到達することです、このプロセスにおけるエネルギー値は、負の単位にすることはできません。
質問は今、エネルギー値は、ゲームを開始するために、ロボット、あなたはゲームが正常に完了したことを確実にすることができますどのくらいですか?
入力形式
N.整数入力の最初の行
2行目は、スペースで区切らN、H(1)、H(整数であり 2)、...、H(N) 、建物の高さを表します。
出力フォーマット
出力整数値が必要とされるエネルギーの最初の最小単位を表します。
データ範囲
\(1≤N、H(I)≤10^ 5 \)
\(1≤N、H(I)≤10^ 5 \)
アイデア:
トピックを分析する1
- エネルギーの量は、ロボットがMAXのすべての建物の高さを有する場合より少ない数のエネルギーよりも建物の高さは、数が高さを構築するエネルギーの数に等しい、エネルギーを増加させるため、次にロボットは、すべての建物を通過できるようになり、エネルギーは数0を増加させるであろう。
- 建物の高さの最小値は1であるため、ロボットは、1であるべき最低限のエネルギーの数を持っています
2.二分法
- 区間[1、最大]
- 分析条件は、中間のために、すなわち、エネルギー値、0 =>(MID)CAL全エネルギーによって建物に残っている場合、裁判官に機能CAL(int型X)を定義する初期エネルギー値も縮小し続けることができることを示し、0よりも大きいです。
コード
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
int num[N];
int cal(int x,int ma)
{
for(int i = 1; i <= n;i++)
{
if(x >= num[i])
x += (x - num[i]);
else
x -= (num[i] - x);
if(x < 0 || x >= ma) //如果超过max,则一定可以通过;如果小于0,则一定不行
break;
}
return x;
}
int main(void)
{
scanf("%d",&n);
int ma = 0;
for(int i = 1 ;i <= n; i++ )
{
scanf("%d", &num[i]);
ma = max(ma,num[i]);
}
//二分法
int l = 1,r = ma;
while(l < r)
{
int mid = (l + r) >> 1;
if(cal(mid,ma) >= 0)
r = mid;
else
l = mid + 1;
}
printf("%d",r);
return 0;
}
私はピットに遭遇しました
)(CAL機能を分析することは初めではありません
if(x < 0 || x >= ma)
break;
データがオーバーフローint型のx、xは本当に悪い蓄積希望した後の範囲につながることができます。私は長い長いXの結果オーバーフローを使用しています。最後に、条件のように、どちらも高速でもオーバーフローも考えるように上記の判断を追加します。
ポイントチョコレート
こどもの日の子供たちは、Kビット暁明の家のゲストを持っています。暁明は、子供たちを楽しませるためにチョコレートのコレクションを思い付きます。暁には、i番目のブロックがHiの長方形である、チョコレートのN個のブロックの合計は、のWi正方形をxは。
公平を期すために、これらのN Kにボブのニーズは、子供たちに与えられたチョコレートチョコレートの部分を切り取ります。チョコレートのニーズを切り取り会いました:
- 形状は、整数の辺長を有する正方形であります
- 同じサイズ
例えば6x5チョコレートは、二つのチョコレートまたはチョコレート6 2x2の3x3のを切り出すことができます。
もちろん、子どもたちはチョコレートのような大きなとして取得することを望んでいる、あなたは小さなこんにちは計算を助ける側の最大の長さはどのくらいでしょうか?
エントリー
最初の行は二つの整数NとK.が含まれています (1 <= N、K < = 100000)
次のNラインは二つの整数のHiとWiを含有します。(1 <=こんにちは、WI < = 100000)
チョコレートで少なくとも1×1で、各学生を確保するための入力を得ることができます。
輸出
チョコレート可能な最大辺の長さの正方形のうち出力カット。
思考
その質問の前に、[1、最大]非常に類似しており、間隔範囲チョコレートサイズは、2分間チョコレート間隔の辺の長さの、場合
決意条件CAL(MID)> = K、すなわち、分離することができるエッジ長ミッドチョコレートは、k個の子どもたちよりも大きい場合、その後、あなたはいくつかのポイントに多くのチョコレートを置くことができるかもしれません。
コード
#include <cstring>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;
typedef long long LL;
const int N = 100010;
int num[N][2];
int n,k;
LL cal(int dat)
{
LL sum = 0;
for(int i = 0; i < n;i++)
{
int x = num[i][0]/dat;
int y = num[i][1]/dat;
sum += x * y;
if(sum >= k)
break;
}
return sum;
}
int main(void)
{
scanf("%d %d", &n,&k);
int ma = 0;
for(int i = 0; i < n;i++)
{
scanf("%d %d",&num[i][0],&num[i][1]);
ma = max(ma,min(num[i][0], num[i][1]));//取所有巧克力中宽的最大值
}
int l = 1,r = ma;
while(l < r)
{
int mid = (l + r + 1) >> 1;
if(cal(mid) >= k)
l = mid;
else
r = mid - 1;
}
printf("%d",l);
return 0;
}
遭遇ピット
最初の境界ゾーンを特定していなかった、私は辺の長さの数、それはあなたがチョコレートのすべての部分を使用したい場合は、確かにすべての最小辺の長さを探しているが、実際にあるため、すべてのチョコレートの権利は、最小の辺の長さであるべきだと思います小さなチョコレートのことを行うことができます。これは、提出、または不十分な思考の後に発見されました。
四平方和
そしてまた、ラグランジュの定理として知られている4つの平方定理、:
各正の整数が4までの正の整数であり、正方形のように表すことができます。
含まれている場合0、それだけで数4の正方形として表現することができます。
例えば:
5 + 2 = 0 ^ 0 ^ 1 ^ 2 + 2 ^ 2 + 2
7 = 1 ^ 1 ^ 2 + 2 + 1 + 2 ^ 2 ^ 2
(^記号は、平均電力を示します)
任意の正の整数を、及び複数の正方形表現が存在してもよいです。
あなたは、請求項4の数分類:
0 <= A <= B <= C <= D
と、B、Cによって可能表現の全てが、Dが小さい順に、主キー、最終出力の最初の表現であります
プログラム入力がN(N <5000000)整数正である
、請求項を出力する4つの非正の整数、昇順に、空白で区切ら
アイデア:
次のように私は、問題の解決策を読み取るために出て、それについてのバイナリと思うに出て行くために始めた、私が出てくるしたくなかった、列挙するために一瞬のために少し思ったが、感情時間:
1.まず計算を列挙の時間複雑:\(\ sqrtの{5 * = 2240 10 ^ 6} \)
3重ループの時間複雑さの推定は、O(\(10 ^ 9 \) )、B Nのほとんどは、小さいので、明らかに、(実際にはタイムアウトの最もデータはタイムアウトしません)。
2.だから列挙を改善するために、一般的なアプローチはしている時間のためにスペースを使用します。この問題では:
- C及びDは、最初の列挙することができる\(C ^ 2 + D ^ 2 \) C、Dダウン格納されている(シーケンシャルストレージ、ハッシュ)の値
- A、Bを列挙計算\(N-T = - ^ A ^ 2 B-2 \) 、またはバイナリハッシュTが格納されているかどうかを決定すること。
- tが存在する場合は、直接出力。
方法1つのハッシュ
使用\(C ^ 2 + D ^ 2 \) 直接ハッシュ関数などの値、いくつかの方法が値を構成することができることが留意されてもよいが、第一辞書最小ので、最初の保持。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 5000010;
int num[N][2];
int n;
int main(void)
{
scanf("%d",&n);
int m = 0;
for(int c = 0; c * c <= n;c++ )
for(int d = c;c * c + d * d <= n;d++)
{
int tmp = c*c + d*d;
if(num[tmp][0] == 0 && num[tmp][1] == 0) //在哈希数组还未赋值的情况下,才允许赋值
{
num[tmp][0] = c;
num[tmp][1] = d;
}
}
for(int a = 0;a * a <= n;a++)
for(int b = a; a * a + b * b <= n;b++)
{
int t = n - a * a - b * b;
if(t == 0 || (num[t][0] != 0 || num[t][1] != 0)) //判断t是否存在,存在则直接输出a b c d
{
printf("%d %d %d %d",a,b,num[t][0],num[t][1]);
return 0;
}
}
return 0;
}
方法2分
半、その後、最初のステップは、保存することです\(C ^ 2 + D ^ 2 \) 値を、繰り返した場合、どのようにこれは私が唯一のトラバースを考えることができる、唯一の辞書最低限の秩序を維持しますか、私は、構文、ステッカー、そして学習のためのC ++を知らないギャングプログラムの使用を見て。
//作者:yxc
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 2500010;
struct Sum
{
int s, c, d;
bool operator< (const Sum &t)const
{
if (s != t.s) return s < t.s;
if (c != t.c) return c < t.c;
return d < t.d;
}
}sum[N];
int n, m;
int main()
{
cin >> n;
for (int c = 0; c * c <= n; c ++ )
for (int d = c; c * c + d * d <= n; d ++ )
sum[m ++ ] = {c * c + d * d, c, d}; //不清楚这里是怎么处理有多种方法可以构成一个值的
sort(sum, sum + m);
for (int a = 0; a * a <= n; a ++ )
for (int b = 0; a * a + b * b <= n; b ++ )
{
int t = n - a * a - b * b;
int l = 0, r = m - 1;
//二分
while (l < r)
{
int mid = l + r >> 1;
if (sum[mid].s >= t) r = mid;
else l = mid + 1;
}
if (sum[l].s == t)
{
printf("%d %d %d %d\n", a, b, sum[l].c, sum[l].d);
return 0;
}
}
return 0;
}