• 失格


    【问题描述】
    胆小鬼连幸福都会害怕,碰到棉花都会受伤,有时还被幸福所伤。
    ——太宰治《人间失格》
    回顾我的一生,一共有 n 个事件,每一个事件有一个幸福值 p_i。
    我想用 n-1 条线把所有的事件连起来,变成一个连通块。一条连接了事件 x
    和事件 y 的线会产生 min(p_x mod p_y,p_y mod p_x)的喜悦值。
    日日重复同样的事,遵循着与昨日相同的惯例,若能避开猛烈的狂喜,自然
    也不会有悲痛的来袭。因此,我想知道连接起来之后产生喜悦值最小是多少。
    【输入格式】
    文件第一行有一个正整数 n。
    接下来 n 行,每行一个正整数 p_i。
    【输出格式】
    输出只有一行,表示最小的喜悦值。
    【样例输入输出 1】
    autosadism.in
    4
    2
    6
    3
    11

    autosadism.out

    1
    【样例输入输出 2】
    autosadism.in
    4
    1
    2
    3
    4

    autosadism.out

    0
    【样例输入输出 3】
    autosadism.in
    3
    4
    9
    15

    autosadism.out

    4
    【数据范围】
    对于 30%的数据,保证 1<=n<=10^3。
    对于另外 40%的数据,保证 1<=p_i<=10^6。
    对于 100%的数据,保证 1<=n<=10^5,1<=p_i<=10^7。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 using namespace std;
     7 struct Node
     8 {
     9   int u,v;
    10 }edge[22000001];
    11 int n,num,p[100001];
    12 bool vis[10000001];
    13 int maxp,Nxt[10000002],set[100001],cnt,dis[22000001];
    14 long long ans;
    15 vector<Node>E[10000001];
    16 int find(int x)
    17 {
    18   if (set[x]!=x) set[x]=find(set[x]);
    19   return set[x];
    20 }
    21 void add(int u,int v,int dis)
    22 {
    23   E[dis].push_back((Node){u,v});
    24 }
    25 int main()
    26 {int i,j,last;
    27   cin>>n;
    28   for (i=1;i<=n;i++)
    29     {
    30       scanf("%d",&p[i]);
    31       if (vis[p[i]]) i--,n--;
    32       else vis[p[i]]=1;
    33       maxp=max(maxp,p[i]);
    34     }
    35   sort(p+1,p+n+1);
    36   int now=n;
    37   for (i=maxp;i>=1;i--)
    38     {
    39       if (now>0&&p[now-1]>=i) now--;
    40       Nxt[i]=now;
    41     }
    42   //for (i=1;i<=maxp;i++)
    43   //cout<<Nxt[i]<<endl;
    44   for (i=1;i<n;i++)
    45     {
    46       int v=p[Nxt[p[i]+1]]%p[i];
    47       add(i,Nxt[p[i]+1],v);
    48       int P=2*p[i];
    49       last=Nxt[p[i]+1];
    50       while (P<=maxp)
    51     {
    52       int v=Nxt[P];
    53       if (v==0) break;
    54       if (last!=v)
    55       {
    56         if (v)
    57         {add(i,v,p[v]%p[i]);}
    58         last=v;
    59       }
    60         P+=p[i];
    61     }
    62     }
    63   for (i=0;i<=maxp;i++)
    64     {
    65       for (j=0;j<E[i].size();j++)
    66     {
    67       ++num;
    68       edge[num]=E[i][j];
    69       dis[num]=i;
    70     } 
    71     }
    72   for (i=1;i<=n;i++)
    73     set[i]=i;
    74   for (i=1;i<=num;i++)
    75     {
    76       int u=find(edge[i].u);
    77       int v=find(edge[i].v);
    78       if (u!=v)
    79     {
    80       set[v]=u;
    81       ans+=dis[i];
    82       cnt++;
    83       if (cnt==n-1) break;
    84     }
    85     }
    86   cout<<ans;
    87 }
  • 相关阅读:
    读取XML数据出错 (十六进制值 0x00)是无效的字符 的解决办法
    随记
    CRM2011:用PublishXmlRequest发布组件
    在CRM2011表单中取消OnSave操作
    Ubuntu下Postfix配置
    .net再学习
    Error registering plugins and/or workflows
    英语语法笔记摘录
    OPENCV MFC 程序出错修改
    win7激活工具使用
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7799477.html
Copyright © 2020-2023  润新知