hdu3916Sequence Decomposition贪心
解:
(引)
比如一个序列2 3 4 3 3 1
如何拆成门函数分量使得长度尽量平均呢? 直观的想法是在消的过程中使序列尽量平均。
首先想到是左边第一个肯定要拆成2个门函数且应使其尽可能长,但也不是越长越好。
如果a[i] <= a[i+1] 那么消掉a[i]的时候,a[i+1]消掉肯定没坏处,因为如果不消,
不仅可能使答案变小,而且序列也会变的更加不平均
如果a[i] > a[i+1] 则本着使序列越来越平均的思想,消掉a[i]的时候自然是不要消掉a[i+1]了。
上述样例采用该贪心方法的过程是
2 3 4 3 3 1 消(1,3)
1 2 3 3 3 1 消(1,5)
0 1 2 2 2 1 消(2,5)
0 0 1 1 1 1 消(3,6)
0 0 0 0 0 0
故答案是3
至于O(n)算法 我方法可能比较抽象 借助左右2个指针i,j 不是每次都对每个数进行减法运算
而是借助 通过lazy操作来不断更新
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=10005;
const int INF=1000000000;
int d[maxn];
int main()
{
int cas,n;
cin>>cas;
while(cas--)
{
cin>>n;
memset(d,0,sizeof(d));
for(int i=1;i<=n;i++)scanf("%d",&d[i]);
int l=1,r=1,lazy=0,ans=INF;
for(int i=1;i<=n;i++)
{
if(d[r]<=d[r+1])r++;
else break;
}
while(l<=r)
{
ans=min(ans,r-l+1);
while(d[l]-lazy==0)l++;
if(d[r]-lazy<=d[r+1])//当需要加入一个新的数时再减掉lazy
{
for(int i=l;i<=r;i++)d[i]-=lazy;
while(l<=r)
{
if(!d[l])l++;
else break;
}
lazy=0;
while(d[r]<=d[r+1])r++;
}
lazy++;
}
cout<<ans<<endl;
}
}