感觉不是很难,但是需要一些思考...
可以发现,贪心地向尽量大的区间添加,但是存在一些比较小的数,它们不需要再加了,就会从那个地方断成两个区间。所以刚开始想到的做法就是统计每一种数的数量,每一次加过之后就能知道现在的一排积木被分成了多少段,每一段都要单独来加一次。
但是,存在整个区间都不需要再加的情况,这个时候这种方法还是会把这个区间再加一次。
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<cstring> 5 #include<queue> 6 #include<map> 7 #include<iostream> 8 #include<stack> 9 using namespace std; 10 #define ll long long 11 #define INF 0x3f3f3f3f 12 #define N 10005 13 int rd() 14 { 15 int f=1,s=0;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();} 17 while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();} 18 return f*s; 19 } 20 int n,cnt[N]; 21 ll ans=0; 22 int main() 23 { 24 int n=rd(),maxx=0; 25 for(int i=1;i<=n;i++) 26 { 27 int tmp=rd(); 28 maxx=max(maxx,tmp); 29 if(i!=1&&i!=n) cnt[tmp]++; 30 } 31 int seg=1; 32 for(int i=1;i<=maxx;i++) 33 { 34 ans+=seg; 35 seg=seg-1+cnt[i]+1; 36 } 37 printf("%lld ",ans); 38 return 0; 39 }
我们发现,一个区间最终需要加的次数等于这个区间中的最大值。把整个数列从递减的地方断开,分成若干个区间。区间中的最大值决定了区间被加的次数,而这个区间中的最小值也很重要,如果前面有数大于最小值的话,这个区间被加的次数的前 最小值 次都可以和上一个区间合并,可以省去 最小值 次。
就做完啦。
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<cstring> 5 #include<queue> 6 #include<map> 7 #include<iostream> 8 #include<stack> 9 using namespace std; 10 #define ll long long 11 #define INF 0x3f3f3f3f 12 #define N 10005 13 int rd() 14 { 15 int f=1,s=0;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();} 17 while(c>='0'&&c<='9'){s=(s<<3)+(s<<1)+(c^48);c=getchar();} 18 return f*s; 19 } 20 int n; 21 ll ans=0; 22 int last=0; 23 int main() 24 { 25 int n=rd(); 26 for(int i=1;i<=n;i++) 27 { 28 int tmp=rd(); 29 if(tmp<last) ans+=last,ans-=tmp,last=tmp; 30 else last=tmp; 31 } 32 ans+=last; 33 printf("%lld ",ans); 34 return 0; 35 }