题目链接:http://codeforces.com/contest/1173/problem/C
赛后又WA了几发才AC,代码是改进过的代码,自己写的又臭又长;
题意:有 n 张带标号的牌和 n 张空白牌(混合),n 张在手上剩下在牌堆里(牌堆有序),每次可以从手上选一张牌放牌堆底部并从牌堆顶部抽一张牌,需要使牌堆从上到下递增地放 1 ~ n,求最小操作数。
思路:如果堆中的牌出现类似这种状况 ~~~~1 2 3 4(就是不用空牌直接完成),就可以判断是否可以直接放牌,如果不可以或者没有这种状况就可以把堆中的牌全部拿到手里(用手中的空白牌),然后依次放进去;
参考别人改进后的代码:
#include<bits/stdc++.h>
#define db double
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=3e5+10;
int len[N];
int vis[N],x[N];
int main()
{
int n;
scanf("%d",&n);
int a,ans=0,j,i;
for(int i=1; i<=n; i++)
{
scanf("%d",&a);
vis[a]=1;
}
for(int i=1; i<=n; i++)
{
scanf("%d",&a);
len[a]=i;
}
if(len[1])
{
for(i=2; len[i]==len[1]+i-1; ++i);
if(len[i-1]==n)
{
for(j=i; j<=n&&len[j]<=j-i; ++j);
if(j>n)
{
printf("%d\n",n-i+1);
return 0;
}
}
}
for(i=1; i<=n; i++)
{
if(vis[i]==0)
ans=max(ans,len[i]-(i-1));
}
printf("%d\n",ans+n);
return 0;
}
自己的代码:
#include<bits/stdc++.h>
#define db double
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=3e5+10;
int len[N];
int vis[N],x[N];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
memset(len,0,sizeof(len));
int a,ans=-inf;
for(int i=1; i<=n; i++)
{
scanf("%d",&a);
vis[a]=1;
}
for(int i=1; i<=n; i++)
{
scanf("%d",&a);
len[a]=i;
}
if(n==1)
{
if(vis[1]==0) printf("0\n");
else printf("1\n");
continue;
}
int flag=0;
for(int i=1; i<=n; i++)
{
if(len[i]!=i)
{
flag=1;
break;
}
}
if(flag==0)
{
printf("0\n");
continue;
}
int tmp=len[1],fla=0,u;
if(tmp==0) fla=1;
for(int i=2; i<=n; i++)
{
if(tmp==n)
{
u=i;
break;
}
if(len[i]!=++tmp)
{
fla=1;
break;
}
}
if(fla==0)
{
int jj=1;
for(int i=u; i<=n; i++)
if(vis[i]==0)
{
if(len[i]>i-u)
{
jj=0;
break;
}
}
if(jj==1)
{
int aaa=0;ans=0;
for(int i=u; i<=n; i++)
{
if(vis[i]==0)
{
ans=max(ans,len[i]-(i-1));
aaa=1;
}
}
if(aaa==1) printf("%d\n",n-u+ans+1);
else printf("%d\n",n-u+1);
continue;
}
}
ans=0;
for(int i=1; i<=n; i++)
{
if(vis[i]==0)
ans=max(ans,len[i]-(i-1));
}
printf("%d\n",ans+n);
}
return 0;
}