CF1151E题解
CF1151E
感觉这种类型的题目都很套路啊,因此写一篇题解来总结一下。
思路
首先看到连通块就应该敏锐地发现:连通块个数 = 点数 - 边数。
因此我们直接考虑分别记录点数和边数对答案的贡献。
对于点数,当前点对答案产生贡献需要满足 \(l\le a_i\le r\),因此会被计算 \(a_i(n-a_i)+1\) 次。
对于边数,对于两个点 \(i\) 和 \(i+1\) 连成的边,只有两个点都被算入答案,整条边才会被算入答案,因此会被计算 \(\min(a_i,a_{i+1}(n-\max(a_i,a_{i+1})+1))\) 次。
总时间复杂度为 \(O(n)\)。
代码
#include<iostream>
using namespace std;
typedef long long ll;
ll n,a,last,res;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++,last=a)
{
cin>>a;
res+=a*(n-a+1)-(i>1)*min(a,last)*(n-max(a,last)+1);
}
cout<<res;
return 0;
}