[DP]トピック - [USACO13OPEN]写真の写真

この質問は非常に良い動きゲージトラックタイトルですが、難しいことではない思考プロセスが大幅に恩恵を受けました。

[9/25更新:2ヶ月のバックファイルまで鳩]

タイトル説明

ファーマージョンはいつものように、便利1..Nから番号が付けられ、彼のN牛のラインアップ(1 <= N <=20万)、のパノラマ写真を組み立てることが決定しました。したがって、彼はそれぞれが牛の連続した範囲をカバーし、M(1 <= M <=10万)の写真をスナップ:写真は、私は牛がb_iを含めてa_iを含んでいます。写真をまとめ、必ずしもすべての単一の牛をカバーしないかもしれません。

彼の写真を撮った後、FJは非常に興味深い現象に気づいた:彼が取ったそれぞれの写真には、スポットと正確に一つの牛が含まれています!FJは、彼が彼の群れにスポット牛をいくつか持っていたことを知っていたが、彼は実際にそれらを数えたことがありませんでした。彼の写真をもとに、彼の群れに存在する可能性が発見牛の可能な最大数を決定してください。出力-1 FJの写真の結果と一致して牛にスポットのない可能性の割り当てがない場合。

ファーマージョンは(1 <= N <= 200,000)家族写真の牛を生産し、N牛がNに1を、番号Nに並んで立つことを決定します

ジョンはその後、M(1 <= M <=10万)写真を撮影し、それぞれの写真は、牛の連続期間をカバー:i番目ピクチャ番号は牛をb_iするa_iを含ま。しかし、これらの写真は、それぞれの牛が内部に撮影されたとは限りません。

:写真撮影の後、ジョンは興味深い見つけ体および斑点を持つ唯一の牛の両方でそれぞれの写真をジョンは、いくつかのスポットでは牛の彼の群れことに気づいたが、その番号に、彼は決して統計。写真によると、あなたは彼の群れにジョンを助けるには、どのように多くのスポット牛までがあるかもしれないと推定します。いいえソリューション、出力した場合「-1。」

入出力フォーマット

入力フォーマット:

* 1行目:二つの整数NとM.

*行2..M + 1:回線I + 1はa_iをしてb_iが含まれています。

出力フォーマット:

* 1行目:FJの農場で発見牛の最大数、または-1は可能な解決策がない場合。

私たちは、タイトルは非常に重要な条件を持っていることを参照してください。「各写真は牛の斑点を持つ、唯一のボディを持っています。」

:F i番目の牛によって選択されたとき牛の最大数を表す[I]、仮定F [i]はJのいずれから転送されます

までの1のみの範囲:

  場合を考える、すべてのセクションでそのエンドポイントjはI左端に配置されなければならない前に [i]は、<= R jと呼ばれる、 [I] R iはすべてのセクションの左端の点を表します。

2.のみ最小間隔:

  このような状況を考慮して、セクションでは、牛は、それがそうである1の場合には、私はカバーまたはセクションが交差している左側のセクション私は、最近のを考慮することができないことをこの位置Iを除いて、すべてのiをカバーそれは、すなわち左セクションI最も近い点の左端点(すなわち最大)に対するIの全ての部分の範囲内で、[i]は、そこJ> = L [i]とLと呼びます。

  要約すると、我々は、Fになってきた[I] =最大{F [J] + 1、L [i]は<= J <= R [I]}。

2:私たちは、LとRを維持する方法を検討してください。

  入力の間隔時間は、[A、B]、この点Bにおいて決定することができる間隔設定、-1ほとんどは、Bの左側値として決定することができる(ただし、左の多くても1つのかどうかわからない)、時間をrと呼ばれます[B] -1 =。同様に、点B + 1、それはその右辺値のいずれか(仮)ことも可能であるため、[B + 1] = Lと呼びます。

  私たちが知っているように、最小間隔が一つだけ番号が含まほどではないので、一歩先のR [i]は、また、Rを作ることができる考える[I] = I-1、最小値和を取ります。

  

今、私たちはより良い答えかどうかを尋ねることがあります。

   :i点、およびI + 1のために、私たちは私+ 1のための範囲の右端場合、2つの可能性が、この間隔があることを知っています

しかしながら、この時間間隔iが個数、R [I + 1] = Iです。

2. I介してこの時間は、R [I + 1] [i]はRよりも可能性が小さいです。

综上两点,其实只要取r[i]=min{r[i],r[i+1]}即可。(情况1根本不用考虑好吗。。。)

l[i]类似,在此不做赘述,l[i]=max{l[i],l[i-1]}。

  接着我们用单调队列来处理这个东西:

  我们在l[i]到r[i]的范围内,找到最大的f[x]更新。

参考了一下大佬的代码,这里有一些小细节:比如可以用n+1来表示是否有解,单调队列的写法等。

 

#include<bits/stdc++.h>
using namespace std;
int read(){
    int x=0,f=1;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(isdigit(c)){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
const int N=2e5+10;
int n,m;
int l[N],r[N],f[N],q[N];
struct cow{
    int a,b;
}t[N];
int main(){
    n=read();m=read();
    for(int i=1;i<=n+1;i++) r[i]=i-1;
    for(int i=1;i<=m;i++){
        t[i]=(cow){read(),read()};
        l[t[i].b+1]=max(l[t[i].b+1],t[i].a);
        r[t[i].b]=min(r[t[i].b],t[i].a-1);
    }
    for(int i=n;i>=1;i--){
        r[i]=min(r[i],r[i+1]);
    }
    for(int i=2;i<=n+1;i++){
        l[i]=max(l[i],l[i-1]);
    }
    int head=1,tail=1;
    int pos=1;
    for(int i=1;i<=n+1;i++){
        while(pos<=r[i]&&pos<=n){
            if(f[pos]==-1){
                pos++;
                continue;
            }
            while(head<=tail&&f[pos]>f[q[tail]]) tail--;
            q[++tail]=pos;
            pos++;
        }
        while(head<=tail&&q[head]<l[i]) head++;
        if(head<=tail) f[i]=f[q[head]]+(i!=n+1?1:0);
        else f[i]=-1;
    }
    printf("%d",f[n+1]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/Nelson992770019/p/11179109.html