[Usaco2005 12月]クリーニングシフト

[Usaco2005 12月]クリーニングシフト

セグメントN間隔、左右端が与えられ\(L_iを、R_iを\) このセクションのコスト選択\(C_I \)を今、選択された間隔の数を、それが完全に間隔カバー\([M、Eは] \) および最小質問、費用\(1≤n≤10000,0≤m≤e≤86399\)

ソリューション

アクトワン:

左端部は、被検体が保証されているが、このように設定し、範囲を選別する場合、大きな範囲を選別することを望むかもしれない\(F_iと\する)、i番目のセクションの前にカバーされるすべての位置をカバーするために、最後までi番目のセクションを表しますこれが最低価格、

\ [F_iと= \ MIN_ {J = 1、r_j + 1 \ GEQ L_iを} ^ {I-1} \ {F_J \} + 1 \]

ボーダー:左のポイントを手動で開始されたすべての大規模な範囲、無限の残りの部分をカバー

答え:の右端カバーする大規模なセクション\(のf_iを\)

これは実際にあることに注意していない\(O(N ^ 2) \) アルゴリズムが、nが比較的小さいため、実際には、これは\(C_N ^ 2 \) 実際には、何の\(^ 8 \ 10)水が持っていたことができるように、 。

参照コード:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
struct interval{
    int l,r,c;
    il bool operator<(const interval&x)const{
        return l<x.l;
    }
}I[10001];
int dp[10001];
int main(){
    int n,m,e;scanf("%d%d%d",&n,&m,&e);
    for(int i(1);i<=n;++i)
        scanf("%d%d%d",&I[i].l,&I[i].r,&I[i].c);
    sort(I+1,I+n+1),memset(dp,1,sizeof(dp));
    ri int i,j;
    for(i=1;i<=n;++i)
        if(I[i].l==m)dp[i]=I[i].c;
        else break;
    while(i<=n){
        for(j=i-1;j;--j)
            if(I[j].r+1>=I[i].l)
                if(dp[j]<dp[i])dp[i]=dp[j];
        dp[i]+=I[i].c,++i;
    }int ans(intmax);
    for(i=n;i;--i)
        if(I[i].r==e)
            if(ans>dp[i])ans=dp[i];
    if(ans<intmax)printf("%d",ans);
    else puts("-1");
    return 0;
}

アクトII:

限り、人々はわずかに超え、大規模なデータ範囲、ゲームを開いて話題に気づいて、水の痕跡がありますが、転送の最適化をサポートしていない、我々は唯一のその第一法則であれば、正のソリューション、M注目し、状態を変更することができ、電子の事実として長い長距離に開始するが、mは、eが入力するように、非常に小さくすることができる\(nlog ^ N \)の範囲は、状態の位置ことが理解されよう。

こうして提供\(F_Jは\) エンドポイントをソート右部を押し列挙間隔I、間隔M jの位置に最小コストを覆うように、その後、困難がありません

\ [F_J = \ MIN_ {L_iを-1 \当量のK \当量R_iを-1} \ {F_ {K} \} + C_I \]

ボーダー:\(1-F_ {M} = 0 \) 残りの無限

答え:同様の法則

私たちが実際に照会fは予告の最小周期が得られているたびに、唯一の入手は更新されませんので、我々は間隔を照会する必要があるので、ツリーまたはツリーラインアレイをするために最適化することができます\ (O(nlog ^ n)は\ )

参照コード:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define intmax 16843009
using namespace std;
il int min(int a,int b){
    return a<b?a:b; 
}
struct interval{
    int l,r,c;
    il bool operator<(const interval&x)const{
        return r<x.r;
    }
    il void read(){
        scanf("%d%d%d",&l,&r,&c),++l,++r;
    }
}I[10001];
struct segment_tree{
    int a[86400];
    struct data{
        int l,r,d;
    }t[345600];
    il void build(int p,int l,int r){
        t[p].l=l,t[p].r=r;
        if(l==r)return (void)(t[p].d=a[l]);
        int mid(l+r>>1),pl(p<<1),pr(pl|1);
        build(pl,l,mid),build(pr,mid+1,r);
        t[p].d=min(t[pl].d,t[pr].d);
    }
    il void change(int p,int x,int v){
        if(t[p].l==t[p].r)return (void)(t[p].d=v);
        int mid(t[p].l+t[p].r>>1),pl(p<<1),pr(pl|1);
        if(x<=mid)change(pl,x,v);if(x>mid)change(pr,x,v);
        t[p].d=min(t[pl].d,t[pr].d);
    }
    il int ask(int p,int l,int r){
        if(l<=t[p].l&&t[p].r<=r)return t[p].d;
        int mid(t[p].l+t[p].r>>1),pl(p<<1),pr(pl|1),ans(intmax);
        if(l<=mid)ans=min(ans,ask(pl,l,r));
        if(r>mid)ans=min(ans,ask(pr,l,r));
        return ans;
    }
}T;
int main(){
    int n,m,e,i;
    scanf("%d%d%d",&n,&m,&e),++m,++e;
    for(i=1;i<=n;++i)I[i].read();
    sort(I+1,I+n+1),memset(T.a,66,sizeof(T.a));;
    T.a[m-1]=0,T.build(1,0,e);
    for(i=1;i<=n;++i)
        T.change(1,I[i].r,min(T.ask(1,I[i].l-1,I[i].r)+I[i].c,T.ask(1,I[i].r,I[i].r)));
    int ans(T.ask(1,e,e));
    if(ans>=intmax)puts("-1");
    else printf("%d",ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/a1b3c7d9/p/10958338.html