E - Enter The Dragon UVALive - 4977

不会写,所以我找到了一份十分优美的代码来学习:请自觉学习set的用法.因为set保证有序,而有序才能二分用lower_bound,返回set中大于某数的最小的值.

思路:确保每一个下雨的池塘之前都被吸干.比如1001不符合,0101符合.我们只要找到下雨的池塘,再找之前一次出现的这个池塘.理论上之前出现的这个池塘应该是要被吸干的,所以我们找与之前一次出现的池塘后面的最近的0,用它来吸干这个池塘

开一个rain数组,存每一天下雨的是哪一个池塘(0则代表没有池塘下雨)

开一个pre数组,初始化为0,存的是下雨的池塘的之前一次下雨的天数.比如 0 1 0 1:在第二天和第四天下雨.则pre[rain[2]]=0,pre[rain[4]]=1;

开一个ans,初始化为0,一旦rain[i]不为0,ans[i]=-1;当然还有ans[*it]=rain[i];(建议先看看代码)

#include<cstdio>
#include<cstring>
#include<string>
#include<string.h>
#include<set>
#include<algorithm>
#include<iostream>
#include<math.h>
#define maxn 1000008
#define ll long long
#define RPG(i,a,b) for(int i=(a);i<(b);i++)
using namespace std;
int rain[maxn],ans[maxn],pre[maxn];
int main()
{
    int T,n,m;
    scanf("%d",&T);
    while(T--)
    {
        memset(pre,0,sizeof(pre));
        memset(ans,0,sizeof(ans));
        scanf("%d%d",&n,&m);
        RPG(i,0,m)
        scanf("%d",&rain[i]);
        bool ok=true;
        set<int> q;
        set<int>::iterator it;
        RPG(i,0,m)
        {
            if(!rain[i])
            {
                q.insert(i);
                continue;
            }
            ans[i]=-1;
            it=q.lower_bound(pre[rain[i]]);
            if(it==q.end())
            {
                ok=false;
                break;
            }
            ans[*it]=rain[i];
            q.erase(*it);
            pre[rain[i]]=i;
        }
        if(!ok)
            puts("NO");
        else
        {
            puts("YES");
            bool f=true;
            RPG(i,0,m)
            if(ans[i]!=-1)
            {
                if(f){
                    f=false;
                    printf("%d",ans[i]);
                }
                else
                    printf(" %d",ans[i]);
            }
            puts("");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pipitongkw1/article/details/81747808
今日推荐