Luogu P1631,2085合成配列、関数の最小値

Luogu P1631シーケンス合併

被験者における初見、2つの長さが必要である(N \)\シーケンス\(A \)\(B \)\(A \)\(B \)の相数の各々から得るために一緒に加え\(N ^ 2 \)ヶ月と、この\(N ^ 2 \)番目及び最小\(N \)

しようとし始め、優先キューと解決列挙することにより、この可能性を考え、ビッグに小さなからの出力を参照してください。

最も簡単な方法は、に行くために、それぞれ、暴力を持っていることですが、正しく適切にタイムアウトします

次の2つの最適化方法

最初:選択的に入ります

なるこれらの2つのシリーズを考えるのは簡単です

\(B_1 + A_1、B_1 + A_2、B_1 + A_3、B_1 + A_4 ... B_1 + A_ {N-1}、B_1 + A_N \)

\(B_2 + A_1、B_2 + A_2、B_2 + A_3、B_2 + A_4 ... B_2 + A_ {N-1}、B_2 + A_N \)

......

\(B_N + A_1、B_N + A_2、B_N + A_3、B_N + A_4 ... B_N + A_ {N-1}、B_N + A_N \)

トピックそのため、Nのような配列、\(a_iを\ A_ 1当量1} + {I \) \(B_i \のLeq B_。1} + {I \)は、単調シーケンスを保証します

これは、最初に各スタックの最初のシーケンス番号であるかもしれません

したがって限り数としてn個の第1の出力番号i + 1の後にスタックにi番目の配列の

複雑である\(O(N \ログ\ N)\) レベルもあってもよいです

\(コード:\)

#include<bits/stdc++.h>
using namespace std;
inline int redn() {                // 快读
    int ret = 0;
    char ch = getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {ret = ret*10+ch-'0';ch=getchar();}
    return ret;
}
int n,cnt(0);
int a[(int)1E5+7],b[(int)1E5+7];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q; // 懒人STL
int main() {
    n = redn();
    for(int i=1;i<=n;++i) a[i] = redn();
    for(int i=1;i<=n;++i) b[i] = redn(),q.push(make_pair(a[1]+b[i],1));
    while(++cnt<=n) {
        printf("%d ",q.top().first);
        int cur = q.top().second;
        int pls = q.top().first;
        q.pop();
        if(cur+1<=n) q.push(make_pair(pls-a[cur]+a[cur+1],cur+1));
    }
    return 0;
}

第二:列挙の数を減らすために

非常に暴力的

上記のシーケンスはなってきました

\(B_1 + A_1、B_1 + A_2、B_1 + A_3、B_1 + A_4 ... B_1 + A_ {N-1}、B_1 + A_N \)

\(B_2 + A_1、B_2 + A_2、B_2 + A_3、B_2 + A_4 ... B_2 + A_ {N-1}、B_2 + A_N \)

......

\(B_N + A_1、B_N + A_2、B_N + A_3、B_N + A_4 ... B_N + A_ {N-1}、B_N + A_N \)

私たちは、およそ考えなければならないので、

それぞれのための\(B_i \)場合、\(B_ {I-1} \) すでに前と\(K \)\(a_iを\)とを計数し、満たさなければならない\(B_i + A_k \ GEQ B_ {I-1} + a_k \)

したがって、ただ配列になる前に、当社{B_iを}開始する(N-iが+ 1 \) \ 数にスタックに

複雑さは、おそらくある時間(O(N \ログ^ \ 2 \ n)が\) のレベルは、ほとんど経験していました

\(コードは\)あきらめません

関数の値が最も小さいLuogu P2085

質問の意味の説明:

以下のための\(N- \)関数\(のf_i(X)= a_iを \倍X ^ 2 + b_i \倍X + C_I \) 各正の整数(X \)\関数値が得られ、最小出力\(M \)番目

ほとんどの関数の値のちょうどシーケンスを構成してしまう、タイトルに追いつきます

\(F_1(1)、F_1(1)、F_1(1)、F_1(1)、...、F_1(INF)\)

\(F_2(1)、F_2(1)、F_2(1)、F_2(1)、...、F_2(INF)\)

\(F_3(1)、F_3(1)、F_3(1)、F_3(1)、...、F_3(INF)\)

...
\(f_n(1)、f_n(1)、f_n(1)、f_n(1)、...、f_n(INF)\)

操作は問題られるように

\(コード:\)

#include<bits/stdc++.h>
using namespace std;
inline int redn() {                                //快读
    int ret = 0;
    char ch = getchar();
    while(ch<'0'||ch>'9') ch = getchar();
    while(ch>='0'&&ch<='9') {ret = ret*10+ch-'0';ch = getchar();}
    return ret;
}
int Equ[23333][3];
inline int Gtv(int x,int n) {                      //取值
    return Equ[n][0]*x*x+Equ[n][1]*x+Equ[n][2];
}
int n,m;
int t[23333];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
int main() {
    n=redn(),m=redn();
    for(int i=1;i<=n;++i) {
        Equ[i][0]=redn(),Equ[i][1]=redn(),Equ[i][2]=redn();
        q.push(make_pair(Gtv(++t[i],i),i));
    }
//  while(!q.empty()) printf("%d ",q.top()),q.pop();
//  return 0;
    int s = 0,mi = (int)1e9+7;
    while(s<m) {
        printf("%d ",q.top().first);
        q.push(make_pair(Gtv(++t[q.top().second],q.top().second),q.top().second));
        q.pop();
        s++;
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/Ax-Dea/p/12158966.html