1.範囲
1.サイトの範囲の選択
アルゴリズムのアイデア:
昇順で右端内のすべてのセクションの1.まず、
左のエンドポイントは昇順場合は、表示されます
、上記のセクションBセクションをそれはセクションの右端に好適である、それはつながるが区間Bには含まれていません任意のポイント。
2.右端に位置決め部と次のセグメントの左端点、および左点と位置決め部よりも右端を見つける間隔ならば、
この場合は、中間部分は、この間隔にわたって位置決めの右端を中性2を有することを示しますサイクルの終わりまで。
3.問題が最も求め間隔どのように多くの互いに素の数に相当します。
正当化:私たちが求めている、ANSに答えると仮定すると、彼らはans≤とans≥cntを証明することができれば、CNT = ANSを証明するためには、CNTです。
(1)明らかにans≤cnt;
(2)時間増分CNTの条件は、2つの間隔のない交差点ではないので、これらのばらばらの間隔をマークし、最終的な答えは以上既にマークされて等しくなければならないので、マークのすべてのセクションのために必要であるからそのans≥cnt回数。
証明されます。ans = CNT
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int , int> PII;
const int N = 100010;
PII range[N];//first是右端点 second是左端点
int ans;
int main()
{
int n;
cin >> n;
for(int i = 0 ; i < n ; i ++)
cin >> range[i]. second >> range[i].first;
sort(range , range + n);
int r = -2e9;
for(int i = 0; i < n ; i++)
{
if(range[i].second > r)
{
ans++;
r = range[i].first;
}
}
cout << ans << endl;
return 0;
}
2.ばらばらの間隔の最大数
アルゴリズム的思考は:まったく同じコードポイントの範囲は、選択した
正当化:
最後の数は、数がRESを得られる最大のANSであると仮定します。
前の質問によると、我々は交差しない解像度間隔の最大値を示し、RESポイントを探し出します。間隔がANS場合は交差していない、とANS>解像度は、各区間の旅行にANSの点を選ぶ必要がありますが、ポイントは、決定された解像度がANS互いに素間隔が存在しない示し、すべてのポイントを満たすのに十分旅してきました。
代码同上
3.パケット間隔
タイトル:与えられたNは、区間[A閉じI、B I(包括的)が交差点が存在しないように、]、これらの間隔のいくつかのグループに分割され、および小できるだけように、各グループ内の任意の2つの内部部分間のグループの数。
考えアルゴリズム:
1.左昇順に間隔の最初の点;
2.右端の点のそれぞれのグループの権利を維持するために小さなヒープルートを宣言
3.各セクションは、新しい左点の範囲を決定する[I] 1次回および小ヒープheap.top(の根の右端)、
heap.pop()> =範囲[I場合 】1次回、 記載新しい間隔セットのために十分に大きいがない、新しいスーパーグループを作成する必要性と、
そうでない場合は、新しい排出部を最小のグループ、グループ、すなわち、右端点heap.top()の右端に(長いそれは便宜のために右の点に直接最小セット放電の新しいセクションを収容することができる限り)。
追加の新しいセットポイント右セクションを更新/ 4.作成し
、[I] .secondがスタックする範囲に直接(1)新しいグループを、
(2)既存のグループ、ポップの組の右端点に加えヒープ、およびプッシュの新しい範囲の右端点をすることができます。
両端揃え:ANSは最小間隔を設定され、間隔が求めているCNTうち
1明らかにANS <CNT =
2.私たちは組み合わせに開くとCNT-1、次のセクションの左端、右端の場合≤すべてのグループ右端、次いで、組み合わせを開くには、この時間範囲を必要とする[I] 1次回CNTグループとグループの存在比が存在するので、交差点(そのまま左昇順の点、新しいセクションの右端を有します小ドット、すなわち、)ケース部を残し、それと組み合わせて共通点をCNT、それは即ちans≥cnt少なくともCNT基で必要である。
証明される:ANS = CNT
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
pair<int , int> range[N];
int main()
{
cin >> n;
for(int i = 0 ; i < n ; i++)
cin >> range[i].first >> range[i].second;
sort(range , range + n);
priority_queue<int , vector<int> , greater<int>> heap;
for(int i = 0 ; i < n ; i++)
{
if(heap.empty() || heap.top() >= range[i].first) ;
else heap.pop();
heap.push(range[i].second);
}
cout << heap.size() << endl;
return 0;
}
4.カバー部
タイトル:Nは区間[A閉じ考えるI、B I ]およびセグメント区間[S、T]を、あなたは間隔、完全に覆わ間隔指定された線分を最小限にするために選択します。
出力セクションの最小数は、完全に出力を覆っていない場合-1。
アルゴリズムのアイデア:
1.まず、左のポイントを昇順に並べ替え、
ST 2.開始点を、以下STがポイントの範囲を左、右のエンドポイント更新STと、最大範囲の右のポイントを選択見つけ、
あなたは左を見つけることができない場合3。 ST点は、所与の範囲のすべてのセクション被覆、またはすることができない-1を介して間隔またはサイクル未満です。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
pair<int , int> range[N];
bool success;
int st , ed;
int ans;
int n;
int main()
{
cin >>st >> ed >> n;
for(int i = 0 ; i < n ; i++)
cin >> range[i].first >> range[i].second;
sort(range , range + n);
for(int i = 0 ; i < n ; i++)
{
int j = i , r = -2e9;//r用来记录右端点最远的点
while(j < n && range[j].first <= st)
r = max(r , range[j++].second);
if(r < st)
{
ans = -1;
break;
}
ans++;
if(r >= ed)
{
success = true;
break;
}
st = r;
i = j -1;
}
if(!success) ans = -1;
cout << ans << endl;
return 0;
}