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
",ans);
28     return 0;
29 }
原文地址:https://www.cnblogs.com/Ressed/p/9735682.html