Mishka and trip(CodeForces - 703B)

Mishka and trip(CodeForces - 703B)

题目描述:

Little Mishka is a great traveller and she visited many countries. After thinking about where to travel this time, she chose XXX — beautiful, but little-known northern country.

Here are some interesting facts about XXX:

  1. XXX consists of n cities, k of whose (just imagine!) are capital cities.
  2. All of cities in the country are beautiful, but each is beautiful in its own way. Beauty value of i-th city equals to ci.
  3. All the cities are consecutively connected by the roads, including 1-st and n-th city, forming a cyclic route 1 — 2 — ... — n — 1. Formally, for every 1 ≤ i < n there is a road between i-th and i + 1-th city, and another one between 1-st and n-th city.
  4. Each capital city is connected with each other city directly by the roads. Formally, if city x is a capital city, then for every 1 ≤ i ≤ n,  i ≠ x, there is a road between cities x and i.
    There is at most one road between any two cities.

Price of passing a road directly depends on beauty values of cities it connects. Thus if there is a road between cities i and j, price of passing it equals ci·cj.
Mishka started to gather her things for a trip, but didn't still decide which route to follow and thus she asked you to help her determine summary price of passing each of the roads in XXX. Formally, for every pair of cities a and b (a < b), such that there is a road between a and b you are to find sum of products ca·cb. Will you help her?

翻译一下:

小MishKa是一个很棒的旅行家,她游览过许多国家。在仔细想了一下这次该去哪玩之后,她选择去XXX——一个美丽,但很小众的北部国家。
这是她选择这个国家的原因——一些有趣的事实:

  1. XXX拥有n座城市,其中有k座作为省会城市。
  2. 这个国家所有的城市都很美丽,但是每一个美丽的城市都有她的独特之处。她特地为每个城市设置了一个“美丽值”,第i座城市的“美丽值”为ci
  3. 每座城市都被许多条道路连接着,从第一座城市到第二座城市,再从第二座城市到第三座城市……再从第n座城市到第1座城市,组成了一个环行路(1-2-3……-n-1)。正式地,对于每一座城市(1 <= i <=n),在第i和第i+1座城市之间会有一条路,另外还有一条路在第n和第一条路之间。
  4. 每一座省会城市都与其他的所有城市有且仅有一条路连接,正式的,如果x城市是省会城市,那么对于除它之外的所有城市(1 <= i <= n,i ≠ x),都会有一条路在它们(i,x)之间。

通过一条路的过路费只取决于这条路所连接的两座城市的魅力值。因此如果在城市i和城市j之间有一条路,那么它的过路费为ci*cj。

Mishka已经开始整理行装,但她仍未决定如何选择路线,所以她想让你帮她算出XXX国家所有道路的过路费之和。。(既然有第四条下边那句话,后边那段文字不知道还有何存在的意义。。除了迷惑我。。。。)


输入

The first line of the input contains two integers n and k (3 ≤ n ≤ 100 000, 1 ≤ k ≤ n) — the number of cities in XXX and the number of capital cities among them.
The second line of the input contains n integers c1, c2, ..., cn (1 ≤ ci ≤ 10 000) — beauty values of the cities.
The third line of the input contains k distinct integers id1, id2, ..., idk (1 ≤ idi ≤ n) — indices of capital cities. Indices are given in ascending order.

翻译一下:

第一行是两个整数n(3 <= n <= 100000)和k(1 <= k <= n)——XXX国家的所有城市及省会城市的个数。
第二行是n个整数c1、c2、……、cn(1 <= ci <= 10000)——每座城市的美丽值。
第三行是k个确切的整数值id1、id2、……、idk(1 <= idi <= n)——每座省会城市在所有城市集合里的序号。


输出

Print the only integer — summary price of passing each of the roads in XXX.

翻译一下

只输出唯一的一个整数——XXX国家的所有道路的过路费之和


题目小贴士

This image describes first sample case:

It is easy to see that summary price is equal to 17.

This image describes second sample case:
![题目小贴士][1]

It is easy to see that summary price is equal to 71.


第一次尝试

一开始做的思路:先设置省会数组,用于区分普通城市和省会城市,再对所有城市进行遍历。遍历过程中,若当前城市为省会,则计算所有与其相连道路的过路费(不包括在它之前遍历到的省会与其之间的道路);若为普通城市,当前结点的下一个结点为头结点,则计算当前城市与头节点之间路径的过路费,加入到总路径中,否则计算当前结点与下一个节点道路的过路费,计算到总路径中。
在代码中用到了双重循环,时间复杂度为O(n2),由于题目限制运行时间是1000ms,粗略估计遍历城市的循环最坏情况下会执行10000*10000=100000000—,一亿次。果然提交后题目报错:Time limit。

#include<stdio.h>
#include<stdlib.h>

#define N 100000

int main()
{
    int n, k;
    int c[N];
    int id[N];
    int sum = 0;
    int iflag;
    int cap[N] = { 0 };
    scanf("%d %d", &n, &k);
    for (int i = 1; i < n + 1; i++)             //初始化城市
    {
        scanf("%d", &c[i]);
    }
    for (int i = 1; i < k + 1; i++)
    {
        scanf("%d", &id[i]);
        cap[id[i]] = 1;
    }                                           //读取省会城市个数

    for (int i = 1; i < n + 1; i++)
    {
        if (cap[i] == 1)
        {
            for (int j = 1; j < n + 1; j++)
            {
                if (j < i&&cap[j] == 1 || i == j)
                {
                    continue;
                }
                else
                {
                    sum += (c[i] * c[j]);
                }
            }
            continue;
        }
        if ((i + 1) % (n + 1) == 0)             //若下一个结点循环至头结点
        {
            if (cap[(i + 2) % (n + 1)] != 1)    //若不为省会
            {
                sum += c[i] * c[1];
                continue;
            }
        }
        else if (cap[(i + 1) % (n + 1)] != 1)       //否则 若不为省会
        {
            sum += c[i] * c[(i + 1) % (n + 1)];
            continue;
        }
    }
    printf("%d", sum);
    return 0;
}

第二次尝试

第二次尝试消去二重循环,改变一种思路。设置了一些辅助变量。
可以先计算全部城市的美丽值之和作为help_sum,省会城市的美丽值之和作为help_sum2,再分别讨论遍历省会城市和普通城市的情况,若为省会城市,则只需计算其与所有城市的过路费之和,再减去与省会城市多算的过路费即为该省会城市所有未走过道路需交过路费;若为普通城市,则判断下个城市再决定是否交过路费。
再次提交显示wrong answer on test 10,原因为设置变量长度太小。int的范围为[-2^31, 2^31-1]即 [-2147483648,2147483647],21亿;long long 的范围为 [-2^63, 2^63-1]即 [-9223372036854775807, 9223372036854775807],100亿亿,更改大数据变量为long long后提交,代码顺利通过。 ^ ^
代码如下:

#include<stdio.h>
#include<stdlib.h>

#define N 100004

int main()
{
    int n, k;
    int c[N];
    int *id;
    long long sum = 0;
    int *cap;
    long long help_sum = 0;
    long long help_sum2 = 0;
    scanf("%d %d", &n, &k);
    if (n<3 || k>n || k < 1)
        return 1;
    cap = (int *)malloc((n + 1) * sizeof(int));
    id = (int *)malloc((k + 1) * sizeof(int));
    for (int i = 1; i < n + 1; i++)             
    {
        scanf("%d", &c[i]);
        help_sum += c[i];
        cap[i] = 0;
    }
    for (int i = 1; i < k + 1; i++)
    {
        scanf("%d", &id[i]);
        cap[id[i]] = 1;
        help_sum2 += c[id[i]];
    }                                           

    for (int i = 1; i < k + 1; i++)
    {
        sum += ((help_sum - c[id[i]])*c[id[i]]);
        sum -= ((help_sum2 - c[id[i]])*c[id[i]]);
        help_sum2 -= c[id[i]];
    }
    for (int i = 1; i < n; i++)
    {
        if (cap[i] != 1 && cap[i + 1] != 1)
        {
            sum += c[i] * c[i + 1];
        }
    }
    if (cap[n] != 1 && cap[1] != 1)
    {
        sum += c[1] * c[n];
    }
    printf("%lld\n", sum);
    return 0;
}

小小总结

这也是一道很简单的题目,并没有涉及复杂的数据结构知识。
感觉该题不过是解法非常难想,各方面限制较多。花了将近半天的时间(12个小时。。)做这么一道题目,从最开始不断地优化时间复杂度,再到一个测试用例无法通过不断检查代码,最终通过使用long long 扩大了变量范围才最终ac。真的是一次对意志力的小考验,差点就没能坚持到ac。所以以后写题目更要注意优化代码,尽量不要使用多重循环,数据如果过大则要使用范围更大的数据类型,更重要的是在以后的刷题路上一定要保持对自己的信心!
[1]: https://odzkskevi.qnssl.com/978f7393c18621d84fea150293a264cc?v=1485951373

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容