zoukankan      html  css  js  c++  java
  • hihocoder 1356 分隔相同整数

    题目:分隔相同整数

    链接:http://hihocoder.com/problemset/problem/1356

    题意:给一个数组,要求重新排列,使得相同的数不在一起,同时字典序最小(先判断第一个整数,再判断第二个,...),无解就输出-1,n范围10万,每个数范围10亿。

    思路:

      好题,记得以前刚开始搞acm的时候见过一道类似的,不过他只要求判断有无解,这题还要输出重排后的序列。可惜比赛的时候没做出来,思路是想到了,问题是时间不够,脑袋晕乎乎的写不下去。

      首先,无解的情况:记maxt为数组中出现次数最多的数的出现次数,如果满足maxt>(n+1)/2肯定无解,这点挺好想的。

      现在我们再来解决重排的问题:

      如果maxt>n-maxt,那么我们肯定要输出maxt对应的数,否则我们就可以输出最小的,有剩余的,不和前一个相同的数,输出一个后对应数的数量就要相应减少了,然后n次循环就可以解决了。

      有了大致思路,我们可以先对原数组排序,然后用num数组记录个数去重压缩(比如2 2 3 3 3 压缩成2 3,num[1]=2,num[2]=3)。因为要重复很多次找出数组中出现次数最多的数,我们可以用线段树保存数值和次数,然后维护最大次数(次数和值)(这点算是线段树最简单的应用了)。然后按上一段讲的规则n次循环就可以了。

    AC代码:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<algorithm>
      4 using namespace std;
      5 #define N 100010
      6 int a[N];
      7 int num[N];
      8 int ao,n;
      9 
     10 struct Node
     11 {
     12   int val;
     13   int num;
     14   int l,r;
     15   int mid()
     16   {
     17     return (l+r)/2;
     18   }
     19 };
     20 Node v[400040];
     21 void build(int l,int r,int rt)
     22 {
     23   v[rt].l=l;
     24   v[rt].r=r;
     25   if(l==r)
     26   {
     27     v[rt].val=l;
     28     v[rt].num=num[l];
     29     return ;
     30   }
     31   build(l,v[rt].mid(),rt<<1);
     32   build(v[rt].mid()+1,r,rt<<1|1);
     33   if(v[rt<<1].num>v[rt<<1|1].num)
     34   {
     35     v[rt].num=v[rt<<1].num;
     36     v[rt].val=v[rt<<1].val;
     37   }
     38   else
     39   {
     40     v[rt].num=v[rt<<1|1].num;
     41     v[rt].val=v[rt<<1|1].val;
     42   }
     43 }
     44 int min(int a,int b)
     45 {
     46   return a<b?a:b;
     47 }
     48 void update(int x,int rt)
     49 {
     50   if(v[rt].l==v[rt].r)
     51   {
     52     v[rt].num--;
     53     return ;
     54   }
     55   if(x<=v[rt].mid())
     56     update(x,rt<<1);
     57   else update(x,rt<<1|1);
     58   if(v[rt<<1].num>v[rt<<1|1].num)
     59   {
     60     v[rt].num=v[rt<<1].num;
     61     v[rt].val=v[rt<<1].val;
     62   }
     63   else
     64   {
     65     v[rt].num=v[rt<<1|1].num;
     66     v[rt].val=v[rt<<1|1].val;
     67   }
     68 }
     69 
     70 void solve()
     71 {
     72   if(v[1].num>(n+1)/2)
     73   {
     74     printf("-1
    ");
     75     return ;
     76   }
     77   int ln=1,pre=-1;
     78   while(n)
     79   {
     80     if(n-v[1].num<v[1].num)
     81     {
     82       pre=a[v[1].val];
     83       printf("%d",pre);
     84       num[v[1].val]--;
     85       update(v[1].val,1);
     86     }
     87     else
     88     {
     89       while(!num[ln]) ln++;
     90       int tl;
     91       if(pre==a[ln]) tl=ln+1;
     92       else tl=ln;
     93       while(!num[tl]) tl++;
     94       printf("%d",a[tl]);
     95       pre=a[tl];
     96       update(tl,1);
     97       num[tl]--;
     98     }
     99     n--;
    100     if(n!=0) printf(" ");
    101   }
    102   printf("
    ");
    103 }
    104 
    105 int main()
    106 {
    107   while(scanf("%d",&n)!=EOF)
    108   {
    109     for(int i=1;i<=n;i++)
    110     {
    111       scanf("%d",&a[i]);
    112     }
    113     sort(a+1,a+1+n);
    114     ao=1;
    115     num[ao]=1;
    116     for(int i=2;i<=n;i++)
    117     {
    118       if(a[i]==a[i-1])
    119       {
    120         num[ao]++;
    121       }
    122       else
    123       {
    124         ao++;
    125         a[ao]=a[i];
    126         num[ao]=1;
    127       }
    128     }
    129     build(1,ao,1);
    130     solve();
    131   }
    132   return 0;
    133 }
  • 相关阅读:
    PHP获取http头信息
    zend studio 改变背景颜色
    WebApp之Meta标签
    js的左右滑动触屏事件
    越狱的 iPhone、iPad 通过网站实现一键安装 ipa 格式的 APP 应用
    移动平台的meta标签神奇的功效
    HTML5 localStorage本地存储实际应用举例
    移动端开发小结
    openSUSE 安装源
    两种方法求Int最值
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5747622.html
Copyright © 2011-2022 走看看