这个题目是在做消除。由于之前一直不会用memcpy,查了一个多小时,简直痛苦。最后还是华丽的TLE了。
然而代码还是附上:
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;
int n,a[100002], b[100002];
int run(int t, int a[], int b[])
{
int m;
for(int i = 1; i<=n; i++)
{
if(a[i] == 0) continue;
m = min(a[i-1], a[i+1]);
b[i] = m<a[i]?m:a[i]-1;
if(b[i] == 0) t--;
}
memcpy(a,b,(n+1)*sizeof(int));
return t;
}
int main()
{
cin>>n;
a[0] = 0;
int count = 0;
for(int i = 1; i<=n; i++)
{
cin>>a[i];
count = count + (a[i]>0?1:0);
}
a[n+1] = 0; b[n+1] = 0; b[0] = 0;
memcpy(b,a,(n+1)*sizeof(int));// why doesn't work?
int ans = 0;
while(count>0)
{
count = run(count,a,b);
ans++;
}
cout<<ans;
return 0;
}
之后看了一下大家的解答。原来就从两边分别dp一次就可以了。分别算左边消除和右边消除所需的最小次数。
所以说啊,动脑比写代码重要多了。
#include<cstring>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;
int n,a[100002], l[100002],r[100002];
int run(int t, int a[], int b[])
{
int m;
for(int i = 1; i<=n; i++)
{
if(a[i] == 0) continue;
m = min(a[i-1], a[i+1]);
b[i] = m<a[i]?m:a[i]-1;
if(b[i] == 0) t--;
}
memcpy(a,b,(n+1)*sizeof(int));
return t;
}
int main()
{
cin>>n;
a[0] = 0;
int count = 0;
for(int i = 1; i<=n; i++)
cin>>a[i];
a[n+1] = l[n+1] = l[0] = r[0] = r[n+1] = 0;
for(int i = 1; i<=n; i++) l[i] = min(a[i],l[i-1]+1);
for(int i = n; i>=1; i--) r[i] = min(a[i],r[i+1]+1);
int maxx = 0;
for(int i = 1; i<=n; i++){
maxx = max(maxx,min(l[i],r[i]));
}
cout<<maxx;
return 0;
}
另外今天做td的时候,发现自己在遍历树的时候总是会忘掉那个记录位置的数的recursive强大功能。需谨记在心。