[题解]Mail.Ru Cup 2018 Round 1

【题目】

C. Candies Distribution

【描述】

n个小朋友排排坐吃糖糖,小朋友从左到右编号1到n。每个小朋友手上有一定数量的糖。对于第i个小朋友来说,编号比他小的小朋友中有li个小朋友拥有的糖比他多,编号比他大的小朋友中有ri个小朋友拥有的糖比他多。已知每个小朋友手上至少有1颗糖、最多有n颗糖,求一种可能的每个小朋友手上的糖的数量的情形,输出YES和一种情形;如果不存在这样的可能,则输出NO。

数据范围:1<=n<=1000,0<=li,ri<=n

【思路】

对于第i个小朋友来说,有li+ri个小朋友比他的糖多,那么给他n-(li+ri)颗糖,即使那li+ri个比他糖多的小朋友拥有的糖的个数都不相同(即糖数分别为n-(li+ri)+1,...,n),也不会出现矛盾。按照这样的思路给大家发了糖之后,验证每个小朋友左右的比他糖多的小朋友的人数是否符合li和ri。如果符合,就输出该方案;否则,不存在可能的方案。

这道题我在比赛中没想出来【还想了好久好久……】,其实当时已经想到了,这实际上就是以“有多少人比自己糖多”给小朋友分组,但当时没想清楚怎么考虑左右关系。事实上,无论最终的分糖方案是什么,“得到相同数量的糖”的小朋友的分组都是一样的,对于每个小朋友进行检查li和ri就可以了。复杂度O(n^2)。

【我的实现】

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 #define MaxN 1020
 9 //int L[MaxN], R[MaxN];
10 int ans[MaxN];
11 
12 struct node
13 {
14     int L, R;
15     int Have;
16 }a[MaxN];
17 
18 int main()
19 {
20     int n;
21     int i, j;
22     int iL, iR;
23     scanf("%d", &n);
24     for(i = 1; i <= n; i++)
25         scanf("%d", &a[i].L);
26     for(i = 1; i <= n; i++)
27         scanf("%d", &a[i].R);
28     for(i = 1; i <= n; i++)
29         a[i].Have = n - a[i].L - a[i].R;
30     for(i = 1; i <= n; i++)
31     {
32         iL = 0;
33         for(j = 1; j < i; j++)
34             if(a[j].Have > a[i].Have)
35                 iL++;
36         iR = 0;
37         for(j = i + 1; j <= n; j++)
38             if(a[j].Have > a[i].Have)
39                 iR++;
40         if(iL != a[i].L || iR != a[i].R)
41         {
42             printf("NO
");
43             return 0;
44         }
45     }
46     printf("YES
");
47     for(i = 1; i <= n; i++)
48         printf("%d ", a[i].Have);
49     return 0;
50 }
View Code

【评测结果】

原文地址:https://www.cnblogs.com/CQBZOIer-zyy/p/9815877.html