欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ3523[Poi2014]Bricks——贪心+堆

程序员文章站 2022-07-13 12:43:03
...

题目描述

有n种颜色的砖块,第i种颜色的砖块有a[i]个,你需要把他们放成一排,使得相邻两个砖块的颜色不相同,限定第一个砖块的颜色是start,最后一个砖块的颜色是end,请构造出一种合法的方案或判断无解。

输入

第一行3个数,n,start,end。
第二行n个数,a[i]。

输出

令m=sigma(a[1..n])。
如果有解输出m个数。
无解输出0。

样例输入

3 3 1
2 3 3

样例输出

3 2 1 3 2 3 2 1

提示

【数据范围】
n,m≤1000000,1≤start,end≤n

  

  为了防止排到后面一样的砖块太多排不开,所以要贪心的每个位置排当前剩余块数最多的颜色的砖块,如果有多个颜色剩余最多,要优先考虑和末尾颜色相同的来防止倒数第二个和最后一个颜色相同。用堆维护当前位置块数最多的颜色取就好了。

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int s,t,n,m;
bool flag;
struct node
{
    int x,y;
};
bool operator < (node a,node b)
{
    if(a.x!=b.x)
    {
        return a.x<b.x;
    }
    if(a.y==t)
    {
        return false;
    }
    return true;
}
priority_queue<node>q;
int ans[1000010];
int main()
{
    scanf("%d%d%d",&n,&s,&t);
    node miku,jhin;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&miku.x);
        m+=miku.x;
        miku.y=i;
        if(i==s)
        {
            miku.x--;
        }
        if(i==t)
        {
            miku.x--;
        }
        if(miku.x<0)
        {
            printf("0");
            return 0;
        }
        q.push(miku);
    }
    ans[1]=s;
    ans[m]=t;
    for(int i=2;i<m;i++)
    {
        miku=q.top();
        flag=false;
        q.pop();
        if(miku.y==s)
        {
            jhin=miku;
            if(!q.empty())
            {
                miku=q.top();
            }
            else
            {
                printf("0");
                return 0;
            }
            q.pop();
            flag=true;
        }
        s=ans[i]=miku.y;
        if(miku.x>1)
        {
            q.push((node){miku.x-1,miku.y});
        }
        if(flag)
        {
            q.push(jhin);
        }
    }
    if(ans[m-1]==ans[m])
    {
        printf("0");
        return 0;
    }
    for(int i=1;i<=m;i++)
    {
        printf("%d ",ans[i]);
    }
}