(模擬+數學)codeforces - 703B Mishka and trip

原題鏈接:

http://codeforces.com/problemset/problem/703/B


題意:

有n個城市,1-n形成一個環,其中有k個省會,每個省會應該和每個城市都連起來。每個城市有一個美麗值,兩城市之間的連路的美麗值爲兩城市美麗值的乘積,要求所有連路的美麗值的總和。


分析:

首先想到的是先把所有情況加起來,再減去會重複的。但是寫起來比較麻煩而且重複的難以理清,而且感覺怎麼寫都會超時。所以我們可以先不考慮省會的城市,連把環路的美麗值加起來,得ans=∑(n < i<=0)beauty[i]*beauty[(i+1)%n],並且記錄所有城市美麗值的和sum(因爲後面考慮首都的時候都是要乘其他的城市的美麗值然後求和)。在考慮首都的時候,只需要減去在sum中減去自己,並且把自己標記,用tmp暫存對於當前首都的sum值,標記是爲了證明當前省會已經和其他所有城市連接過了,並且在sum值中已經減過,然後在處理後面的省會的時候,當相鄰的沒被標記【說明不是省會】,就需要把tmp減掉相鄰的美麗值,因爲在環路中已經計算過,接下來就是ans+=tmp×beauty[cap[i]]。跑完循環就是答案。複雜度O(n)


代碼:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>


#define ll long long
#define ull unsigned long long

using namespace std;

const int maxn=100010;
const int inf=1<<30;

ll be[maxn];
ll ci[maxn];
bool flag[maxn];

int main()
{
    //#define DEBUG

#ifdef DEBUG
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif

    int n,k;
    scanf("%d%d",&n,&k);
    ll sum=0;
    ll ans=0;
    for(int i=0;i<n;i++){
        scanf("%I64d",&be[i]);
        sum+=be[i];
    }
    for(int i=0;i<n;i++){
        ans+=be[i]*be[(i+1)%n];
    }
    for(int i=0;i<k;i++){
        scanf("%I64d",&ci[i]);
    }
    ll tmp;
    for(int i=0;i<k;i++){
        if(!flag[ci[i]-1]){
            sum-=be[ci[i]-1];
            flag[ci[i]-1]=1;
        }
        tmp=sum;
        if(!flag[(ci[i]-2+n)%n]){
            tmp-=be[(ci[i]-2+n)%n];
        }
        if(!flag[(ci[i])%n]){
            tmp-=be[(ci[i])%n];
        }
        ans+=tmp*be[ci[i]-1];
    }
    printf("%I64d\n",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章