[归并排序][枚举]JZOJ P3967 Counting Friends

Description

FJ 的N 头奶牛(2<= N<= 500)都加入了社交网络“哞不可” 。
每头奶牛有一个或多个与它们自己在哞不可上互相关注的朋友。为了好玩,FJ 制作了一个列表,记下每头奶牛的朋友数目。但是,在书写列表的过程中,农夫John 惆怅了,以至于他错误地写下了一个额外的数字(因此他的列表包含N + 1 个数字,非他预计的N 个数字)。
请帮助FJ 找出在他的列表中有哪些数字可以是那个错误的额外数字。
 

Input

第一行:整数N。
第2 至N + 2 行:第i + 1 行包含FJ 的某一头奶牛的朋友数量,或者也许是那个错误的额外数字。

Output

第一行:一个整数K 给出在FJ 的列表中有多少项目可能是那个额外的数字(或者,K = 0 意味着没有一个数字,移除后可以产生一个可行的朋友配对)。
第2 至K + 1 行:每行包含可能是额外的数字按照输入顺序产生的序号(1到N +1)——也就是说,一个移除后,剩下的N 个数字符合奶牛们某一个可行
的朋友关系集合。这K 行的序号须按从小到大排列。
 

Sample Input

4
1
2
2
1
3

Sample Output

3
1
4
5
样例解释:
FJ 有4 头奶牛。两头每头只有一个朋友,两头各有两个朋友,还有一头有三个朋友(当然,这些数字其中一个是额外的并且不属于这个列表)。
移除FJ 列表的第一个数字(数字1)之后会得到一个剩下的数字2,2,1,3 组成的列表,并且符合一个可行的朋友关系配对——例如,如果我们将奶牛从A
到D 命名,那么配对(A;B); (A;C); (A;D) 以及(B;C) 就足够了,这是因为A有三个朋友,B 和C 都各有两个朋友,还有D 有一个朋友。同理,从FJ 的列表里移除另外一个“1”也是可行的,还有移除“3”也可以。从FJ 的列表里移除任意一个“2”都不可——我们可以看到剩下数字的和是奇数,明显我们无法凑出一个对应的配对。
 

Data Constraint

对于9% 的数据,N <=10。
对于27% 的数据,N <=100。

题解

  • 这题用的是比较暴力的方法
  • 首先,我们知道该数字可以为额外的话,也就是其他的n个都可以匹配成需要那样、
  • 那么就暴力枚举n+1个数,判断哪个可以为额外的数字
  • 怎么匹配呢
  • 其实有一种很简单的想法
  • 就是从大到小排序,向后匹配(也就是往后的2~a[1]+1个都减1)
  • 如果是可以匹配的数的话,这个方法一定是可以匹配的
  • 那么我们考虑一下时间复杂度,每次一个数要O(n^2(n+n*log2n))
  • 只能过6个点
  • 那么快排的时间可以不可以更优呢?
  • 考虑一下,减完之后的序列为0+有序的序列(2~a[1]+1)+有序的序列(a[1]+2~n)
  • 有那种方法是可以直接在O(n)的时间下合并两个有序的序列呢?
  • 显然归并排序
  • 最后判断一波,输出,AC,perfect

代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 bool cmp(int x,int y){ return x>y; }
 6 int n,a[510],x[510],y[510],tot,total,ans[510];
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for (int i=1;i<=n+1;i++) scanf("%d",&a[i]);
11     for (int i=1;i<=n+1;i++)
12     {
13         tot=0;
14         for (int j=1;j<=n+1;j++) 
15             if (i!=j)
16                 x[++tot]=a[j];
17         sort(x+1,x+n+1,cmp);
18         while (x[1]>0)
19         {
20             for (int j=2;j<=x[1]+1;j++) x[j]--;
21             int l1=2,r1=x[1]+1,l2=x[1]+2,r2=n; 
22             tot=0; x[1]=0;
23             while (l1<=r1&&l2<=r2)
24             {
25                 if (x[l1]<=x[l2]) y[++tot]=x[l2],l2++;
26                 else y[++tot]=x[l1],l1++;
27             }
28             while (l1<=r1) y[++tot]=x[l1],l1++;
29             while (l2<=r2) y[++tot]=x[l2],l2++;
30             for (int j=1;j<=n;j++) x[j]=y[j];
31         }
32         sort(x+1,x+n+1,cmp);
33         if (x[n]==0) ans[++total]=i;
34     }
35     printf("%d\n",total);
36     for (int i=1;i<=total;i++) printf("%d\n",ans[i]);
37     return 0;
38 }

 

posted @ 2018-03-13 21:06  BEYang_Z  阅读(172)  评论(0编辑  收藏  举报