bzoj1345 序列问题 (贪心)
考虑某个点产生的贡献:
如果i左边是一个比它小的数x,那有两种情况:
1.x的左边的数y大于i,肯定要把x合并到i,i的贡献++
2.x的左边的数y小于i,那肯定要把x合并到y,而这时候递归地来考虑,总有一天y或更左边的一个数是要合并到i上的,i的贡献++
如果i左边的数x比它大,那就把i合并到x,不是考虑这个点的时候需要计算的
对于右边是同理的
也就是说,每个点的贡献就是它相邻左右两边<它的个数
如果有相等的话,我们这两个要么把左边的合并到右边,要么右边的合并到左边,所以在统计左右的时候一边允许取等一边不允许就行了
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e6+10; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 int N,a[maxn]; 16 ll ans=0; 17 18 int main(){ 19 //freopen("","r",stdin); 20 int i,j,k; 21 N=rd(); 22 for(i=1;i<=N;i++) a[i]=rd(); 23 for(i=1;i<=N;i++){ 24 if(i>1&&a[i-1]<=a[i]) ans+=a[i]; 25 if(i<N&&a[i+1]<a[i]) ans+=a[i]; 26 } 27 printf("%lld\n",ans); 28 return 0; 29 }