码迷,mamicode.com
首页 > 其他好文 > 详细

hihocoder 1356 分隔相同整数

时间:2016-08-08 00:54:11      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:

题目:分隔相同整数

链接: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\n");
 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("\n");
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 }

 

hihocoder 1356 分隔相同整数

标签:

原文地址:http://www.cnblogs.com/hchlqlz-oj-mrj/p/5747622.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!