CodeForces - 1151E 思维

\sum _{l=1}^{n}\sum_{r=l}^{n} f(l,r)是很难简单计算的 我们换一个角度去看 看每一个位置i 对答案的贡献是多少 但是i位置必须得是联通块 才会有贡献 所以我们要对lr进行适当筛选才能计算贡献 

首先对于位置i我们计算它作为联通块右端点的贡献 

那要如何计算呢 

例如  序列  2 5 1 3 4     

我们要让位置1的2作为联通块右端点 首先2要属于l和r 那么 l的取值范围 就是1-2  其次我们要让第2个位置的5和第一个位置的2不在同一个联通块内  那么r的选取不能包括5 (但必须包括2)所以r的取值范围是 2-4  

因此1位置作为联通块右端点的贡献是  (2-1+1)*(4-2+1) 我们可以写成 a[i]*(a[i+1]-a[i]) 

这是 a[i]<a[i+1]的情况  a[i]>a[i+1]大家可以自己推一下  a[i]==a[i+1]时 a[i]显然不可能作为联通块右端点 我们不需要考虑

最后 边界条件 a[n+1]=n+1 这样可以保证 在n位置计算的答案是正确的(可以手动算一下)

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
typedef long long ll;
ll a[N];
int main(){
	int n;
	scanf("%d",&n);
	for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
	a[n+1]=n+1;
	ll ans = 0;
	for(int i = 1; i <= n; i++){
		if(a[i+1]>a[i]) ans+=a[i]*(a[i+1]-a[i]);
		if(a[i+1]<a[i]) ans+=(a[i]-a[i+1])*1ll*(n-a[i]+1);
	}
	printf("%lld\n",ans);
	return 0;
}
原创文章 85 获赞 103 访问量 2505

猜你喜欢

转载自blog.csdn.net/weixin_43824564/article/details/105539450