思路:
如果遇到一个暴雨天,即a[i]!=0的日子
就找在这个日子之前,且在上一次a[i]之后的日子里的晴天.
我直接用了map来存一个x号池塘的上一次出现的位置.
即只需找从中的晴天(由贪心,应该尽量靠前,才能保证有尽量多的雨天能分配到晴天的日子让龙来吸水)
这题修改了许多次
第一次想用vector来存晴天的日子,然后从vector中找大于m[x]的第一个日子,结果TLE
for(int i=1;i<=day;i++)
{
int x;
scanf("%d",&x);
d[i]=x;
if(x==0)
{
w.push_back(i);
}
else
{
if(w.size()==0)
{
ok=0;
}
else
{
auto k=w.begin();
for(;k!=w.end();k++)
{
if(*k>=m[x])
{
break;
}
}
if(k==w.end())
{
ok=0;
}
else
{
num[*k]=x;
w.erase(k);
}
}
m[x]=i;
}
}
第二次采用二分在vector中找,结果还是TLE.
for(int i=1;i<=day;i++)
{
int x;
scanf("%d",&x);
d[i]=x;
if(x==0)
{
w.push_back(i);
}
else
{
if(w.size()==0)
{
ok=0;
}
else
{
auto k=w.begin();
int l=0,r=w.size()-1;
while(l<r)
{
int mid=(l+r)/2;
//printf("%d vs %d\n",w[mid],m[x]);
if(w[mid]>=m[x]) r=mid;
else l=mid+1;
}
k+=l;
// for(;k!=w.end();k++)
// {
// if(*k>=m[x])
// {
// break;
// }
// }
if(k>=w.end()||w[l]<=m[x])
{
ok=0;
}
else
{
num[*k]=x;
// printf("第%d\n",*k);
w.erase(k);
}
}
m[x]=i;
}
}
最后采用了set来存储才AC
s.lower_bound(x) 表示集合s中不小于x的最小的数
AC代码献上
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;
const int N=1e6+10;
int d[N]={0};
int num[N]={0};
int main()
{
//freopen("uva1623.txt","r",stdin);
//freopen("uva1623-out.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
memset(d,0,sizeof d);
memset(num,0,sizeof num);
int num_lake=0,day=0;
scanf("%d%d",&num_lake,&day);
//const int N=1e6+10;
set<int> w;
map<int,int>m;
int ok=1;
for(int i=1;i<=day;i++)
{
int x;
scanf("%d",&x);
d[i]=x;
if(x==0)
{
w.insert(i);
}
else
{
if(w.size()==0)
{
ok=0;
}
else
{
auto k=w.lower_bound(m[x]);
if(k!=w.end())
{
num[*k]=d[i];
w.erase(k);
}else ok=0;
}
m[x]=i;
}
}
if(ok)
{
printf("YES\n");
int haveprint=0;
for(int i=1;i<=day;i++)
{
if(d[i]==0)
{
if(haveprint)
{
printf(" ");
}
printf("%d",num[i]);
haveprint=1;
}
}
printf("\n");
}
else printf("NO\n");
}
return 0;
}