codeforces1151 E. Number of Components(计数)

E. Number of Components

方法一:考虑每个点的贡献,认为一个联通块里让编号最大的点产生贡献
那么,对于一个点 i i i,如果对答案产生贡献,一定要点 i i i 存在,而点 i + 1 i + 1 i+1 不存在。

#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
constexpr int N=100010;
ll a[N];
int n;
int main()
{
    
    
    IO;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    ll res=0;
    for(int i=1;i<n;i++)
    {
    
    
        ll x=a[i],y=a[i+1];
        if(x>y)
            res+=1ll*(n-x+1)*(x-y);
        else
            res+=1ll*(y-x)*x;
    }
    res+=a[n]*(n-a[n]+1);
    cout<<res<<'\n';
    return 0;
}

方法二连通块数量=点数-边数于是点数和边数分开统计
点在连通块中的情况,对于 ( i , i + 1 ) (i,i+1) (i,i+1)这条边要在连通块中必须要求 i , i + 1 i,i+1 i,i+1同时在于是直接计算即可

#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
constexpr int N=100010;
ll a[N];
int n;
int main()
{
    
    
    IO;
    cin>>n;ll res=0;
    for(int i=1;i<=n;i++) 
    {
    
    
        cin>>a[i];
        res+=a[i]*(n-a[i]+1);
    }
    for(int i=1;i<n;i++)
    {
    
    
        ll x=a[i],y=a[i+1];
        res-=min(x,y)*(n-max(x,y)+1);
    }
    cout<<res<<'\n';
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/113777425