水完A题艰难的刷出了B,看到10e5整个人都不好了 这难度梯度也太大了吧摔! 后来想到了乘法分配律O(n)暴力....
首先记录首都节点 然后非首都节点每次连接下一个城市,首都节点则连接除自己和前一个城市外的所有城市,注意重复的情况和i==1,i==n的情况。
附AC代码:
#include<iostream>
#include<cstring>
using namespace std; int a[];
int v[]; int main(){
int n,k;
memset(a,,sizeof(a));
memset(v,,sizeof(v));//初始化为0
cin>>n>>k;
long long sum1=,sum2=;
for(int i=;i<=n;i++){
cin>>a[i];
sum1+=a[i];//所有点值的和
}
int x;
for(int i=;i<k;i++){
cin>>x;
v[x]=;//记录首都节点
}
for(int i=;i<=n;i++){
if(v[i]){//判断是否是首都
if(i==){//1和n时特判
sum2+=a[]*(sum1-a[n]-a[]);
if(v[n]){
sum2+=a[]*a[n];
}
}
else{//连接除自身和前一个点外的所有点
sum2+=a[i]*(sum1-a[i]-a[i-]);
if(v[i-]){//若前一个点也为首都则连接两点
sum2+=a[i]*a[i-];
}
}
sum1-=a[i];//减掉已全连过的首都节点 避免重复
}
else{//连接自己和下一个点 n时特判
if(i==n){
sum2+=a[]*a[n];
}
else{
sum2+=a[i]*a[i+];
}
}
}
cout<<sum2<<endl;
return ;
}