テスト1023 T1およびT2

T1のpopust(貪欲

TIMELIMIT:1000msで
メモリ制限:32768キロバイト

クマのように空腹ミルコ、彼は地元のレストランに出くわし。レストランの申し出\(N \)指定された2つの価格、各食事:シード食事は、興味深い価格政策がある\(a_iを\)\(B_i \) 食事は唯一の最初の価格を支払うために使用することができますミルコ\(A \) 後者ができる唯一の賃金\(B \)価格。彼は食事は一度だけ設定することができますが、彼から知りたかったので、いくつかは、順番に何を知らない知られている\(1 \)に種を\(N \)最小コストの種のために(実際には、彼が何を食べて終わりでは気にしませんでした種)。彼はそれについて考える助けてください。

入力

入力の最初の行は正の整数を含んでいる(N(2≤N≤500000)\)\、レストランによって提供される食事の種類の数。
以下\(N \)線は、2つの正の整数、含ま\(a_iを\)\(B_i \)を(バイ≤000 1 000 000(1≤あい、)\)\表し\(I \)種子ミール2個の価格。

出力:\
(N \)ライン、\(I \)ラインは正確に設定表し\(I \)最低価格シード食事

入力

3
10 5
9 3
10 5

出力

9
13
18

入力

2
100 1
1 100

出力

1
2

入力

5
1000000000 1000000000
1000000000 1000000000
1000000000 1000000000
1000000000 1000000000
1000000000 1000000000

出力

1000000000
2000000000
3000000000
4000000000
5000000000

意味その選挙\(X \)に支払う商品の種類、\(a_iをを\) 残りが支払われる\(B_i \)

以来(a_iを\)は\だけで、我々は分けて考えます。

あなただけ取れば\(Bを\) 我々は小さなから大規模に連れて行く必要があります。

まずソート;

私たちは、大に最初の小さなを取った(X \)\ \(B \)今変更たい、\(A \)を

変更には2つの方法があります。

  • 選挙の前に\(X \)\(B \)に対応する1 (A \)は\、この記事\(a_iを-B_i \) 前者がなければなりません(X \)\最小;
  • これは選択された最小値に選択されていない\(A \) 最大\(B \)に変更。

第二に、我々は、プリアウトができる\(ミナ[] \)を表しを\(I + 1 \ SIM N \) 最小\(A \)

最初は、養子移入を解くことで可変とすることができます。

時間の複雑さがある\(O(nlogn)\)

\(コード\)

#include<bits/stdc++.h> 
#define ll long long 
using namespace std;
const int N=500005;
int n,pos;
struct food
{
    int x,y;
    bool operator<(food w)const
    {
        return y<w.y;
    }
}a[N];
ll minx[N],minc;
ll ans;
inline int read()
{
    int x=0,f=1;char st=getchar();
    while(st<'0'||st>'9'){if(st=='-') f=-1;st=getchar();}
    while(st>='0'&&st<='9') x=x*10+st-'0',st=getchar();
    return x*f;
}

int main()
{
    freopen("popust.in","r",stdin);
    freopen("popust.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].x=read(),a[i].y=read();
    }
    sort(a+1,a+1+n);
    minx[n]=9999999999999;
    for(int i=n-1;i>=1;i--)
        minx[i]=min(minx[i+1],(ll)a[i+1].x);
    minc=9999999999999;
    for(int i=1;i<=n;i++)
    {
        minc=min(minc,(ll)a[i].x-a[i].y);
        ans+=a[i].y;
        printf("%lld\n",min(ans-a[i].y+minx[i],ans+minc));
    }
    
    
    fclose(stdin);
    fclose(stdout);
    return 0;   
}

T2のinformacije(図二部

TIMELIMIT:1000msで
メモリ制限:32768キロバイト

シーケンス\(A \) 封入\(1 \)\(N \) CO \(N \)を与えるための要素(各要素は一度だけ表示される)\(M \)を約番目の\ (\)が記述されています。次のように記述形式は次のとおり
。$ 1×Y V $の位置を表し\([Y、X、] \の ) 最大値の間に等しい\(V \)
\(2 \ X \ Y \ Vは、\)の位置を表し\([X、Yを] \)最小の間の値に等しい)\(V \
出力が上記満たしてください)(M \ \配列が本明細書に記載しました。あなたは、どちらかの出力、異なるオプションを有することができます。

出力は解しない\( - 1 \)

\(N(1≤N≤200)\)\(M(0≤M≤40 000)\)


それは法的な配置を求めています。

どのような数は置くことができる位置を求めています。

片側は、位置が、一方の側が偶数1側を選択することができるナンバーワンの場所です。

これは二部グラフです。

代表位置に関連付けられ、この位置番号は、この番号から選択されます。

これは、二部グラフの最大マッチングです。

マッチが完全でない場合は、それが整列ないように構成されています。

出力\( - 1 \)

前処理は、各位置の数を置くことができ、それぞれの位置番号が偶数エッジ、性的満足場合、置くことができます。

時間の複雑さはある(O(N ^ 3)\ \)

\(コード\)

#include<bits/stdc++.h> 
#define ll long long 
using namespace std;
const int N=205;
int n,m,opt,l,r,v,ans;
bool pd[N][N];
int l1[N],l2[N];//上界,与下界
struct skr
{
    int to,nxt;
}a[N*N*2];
int head[N<<1],cnt;
int match[N<<1],vis[N<<1];
inline void add(int x,int y)
{
    a[++cnt].to=y;a[cnt].nxt=head[x];head[x]=cnt;
}
inline int read()
{
    int x=0,f=1;char st=getchar();
    while(st<'0'||st>'9'){if(st=='-') f=-1;st=getchar();}
    while(st>='0'&&st<='9') x=x*10+st-'0',st=getchar();
    return x*f;
}

inline bool dfs(int x)
{
    for(int i=head[x];i;i=a[i].nxt)
    {
        int y=a[i].to;
        if(!vis[y])
        {
            vis[y]=1;
            if(!match[y]||dfs(match[y]))
            {
                match[y]=x;
                return 1;
            }
        }
    }
    return 0;
}

int main()
{
    freopen("informacije.in","r",stdin);
    freopen("informacije.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;i++)
        l1[i]=n,l2[i]=1;
    while(m--)
    {
        opt=read();l=read();r=read();v=read();
        for(int i=1;i<l;i++)
            pd[v][i]=1;
        for(int i=r+1;i<=n;i++)
            pd[v][i]=1;
        if(opt==1)
        {
            for(int i=l;i<=r;i++)
                l1[i]=min(l1[i],v);
        }
        else
        {
            for(int i=l;i<=r;i++)
                l2[i]=max(l2[i],v);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=l2[i];j<=l1[i];j++)
            if(!pd[j][i]) 
            {
                add(j,i+n);
                add(i+n,j);
            }
    }
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof vis);
        if(dfs(i)) ans++;
    }
    if(ans<n)
    {
        printf("-1");
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    for(int i=1;i<=n;i++)
        printf("%d ",match[i+n]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

おすすめ

転載: www.cnblogs.com/yudes/p/12012459.html