[La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017]Ambiguous Dates

来源:互联网 发布:centos 7 minimal桌面 编辑:程序博客网 时间:2024/05/19 20:45

time limit:per test 1.0 s
memory limit:per test 256 MB

There are two popular formats for representing a date: day/month/year or month/day/year. For example, today can be represented as 15/8/2017 or 8/15/2017.
Sometimes (like on today), using one way or another should pose no confusion — it is immediately understood that the date is the 15th of August. On other days, however, the two representations may be interpreted as two different valid dates. For example, the 7th of August may be misinterpreted as the 8th of July, since both can be represented as 7/8/2017 (or 8/7/2017).
We say a date (D, M, Y) is ambiguous if D/M/Y and M/D/Y, when both interpreted in the day/month/year format, are different valid dates. For example, (7, 8, 2017) and (8, 7, 2017) are ambiguous, while (15, 8, 2017) and (10, 10, 2017) are not.
The total number of ambiguous dates in the Gregorian calendar system on any given year is equal to 12 × 11 = 132.
Now, suppose that in a hypothetical calendar system, there are M months, where the i-th month has D[i] days, numbered from 1 to D[i]. Assume that there are no leap years.
You are to carry out a calendar reform, by shuffling the array D[], and your target is to minimize the total number of ambiguous dates in a calendar year. Specifically, you want to find a permutation p[1], p[2], …, p[M] of integers 1, 2, …, M, such that the new calendar system, where the i-th month has D[p[i]] days, has the minimal number of ambiguous dates. Output that minimal number.

Input

The first line of input consists of a single integer M, the number of months in the hypothetical calendar system.
The second line of input consists of M integers D[1], D[2], …, D[M], the original number of days in the i-th month.
For all test cases, 1 ≤ M ≤ 10^5, 1 ≤ D[i] ≤ 10^5.

Output

Output a single integer, the minimal number of ambiguous dates after the calendar reform.

Examples

input 1

1231 28 31 30 31 30 31 31 30 31 30 31

output 1

132

input 2

35 1 1

output 2

0

吐槽:我觉得,题目太长……讨厌细节题……
题意:有两种表示日期的方法(1)月/日/年 (2)日/月/年。所以在不同的方式下这种表示的日期容易混淆。我们设定一年有M个月,第i个月的天数是D[i],你可以随意交换任意两个月的天数,交换次数不限,使得最后得到的一年的各个月的天数的时候,出现混淆的日期的数量最少,输出最少的混淆日期数量。

题解:很显然我们可以知道如果日期从小到大排序的话,出现混淆的日期数的数量最少。但是算这个数量就比较蛋疼了。对于第i月,我们需要知道:在它前面的几个月中,天数大于等于min(i-1,D[i])的月份有多少个,为什么是min(i-1,D[i])呢?因为如果D[i]小于i-1的话那不就有可能不会出现(i月x日[x < i])那么(x月i日)就不会出现混淆。然后答案需要乘2,因为这些算的都是形如(i月x日[x < i])的、符合混淆条件的日期的数量,那么(x月i日[x < i])也是混淆日期呀,所以答案要乘2。
找天数大于等于min(i-1,D[i])的月份可以用树状数组。

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>#define LiangJiaJun main#define MAXN 100001using namespace std;int m,d[100004];int tr[100004];long long ret=0;inline int lowbit(int x){return x&(-x);}void add(int x,int val){     for(int i=x;i<=MAXN;i+=lowbit(i))tr[i]+=val;}int query(int x){    int ans=0;    for(int i=x;i;i-=lowbit(i))ans+=tr[i];    return ans;}int LiangJiaJun(){    scanf("%d",&m);    for(int i=1;i<=m;i++)scanf("%d",&d[i]);    sort(d+1,d+m+1);    for(int i=1;i<=m;i++){        ret += i-1-query(min(i-1,d[i]));        add(d[i],1);    }    printf("%I64d\n",ret<<1);    return 0;}