zoukankan      html  css  js  c++  java
  • (模拟+数学)codeforces

    原题链接:

    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)


    代码:

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<vector>
     5 #include<set>
     6 #include<map>
     7 #include<algorithm>
     8 #include<string>
     9 #include<queue>
    10 #include<cmath>
    11 #include<stack>
    12 #include<cctype>
    13 #include<list>
    14 
    15 
    16 #define ll long long
    17 #define ull unsigned long long
    18 
    19 using namespace std;
    20 
    21 const int maxn=100010;
    22 const int inf=1<<30;
    23 
    24 ll be[maxn];
    25 ll ci[maxn];
    26 bool flag[maxn];
    27 
    28 int main()
    29 {
    30     //#define DEBUG
    31 
    32 #ifdef DEBUG
    33     freopen("in.txt","r",stdin);
    34     //freopen("out.txt","w",stdout);
    35 #endif
    36 
    37     int n,k;
    38     scanf("%d%d",&n,&k);
    39     ll sum=0;
    40     ll ans=0;
    41     for(int i=0;i<n;i++){
    42         scanf("%I64d",&be[i]);
    43         sum+=be[i];
    44     }
    45     for(int i=0;i<n;i++){
    46         ans+=be[i]*be[(i+1)%n];
    47     }
    48     for(int i=0;i<k;i++){
    49         scanf("%I64d",&ci[i]);
    50     }
    51     ll tmp;
    52     for(int i=0;i<k;i++){
    53         if(!flag[ci[i]-1]){
    54             sum-=be[ci[i]-1];
    55             flag[ci[i]-1]=1;
    56         }
    57         tmp=sum;
    58         if(!flag[(ci[i]-2+n)%n]){
    59             tmp-=be[(ci[i]-2+n)%n];
    60         }
    61         if(!flag[(ci[i])%n]){
    62             tmp-=be[(ci[i])%n];
    63         }
    64         ans+=tmp*be[ci[i]-1];
    65     }
    66     printf("%I64d
    ",ans);
    67     return 0;
    68 }
     
  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/tak-fate/p/5765973.html
Copyright © 2011-2022 走看看