In the evening, after the contest Ilya was bored, and he really felt like maximizing. He remembered that he had a set ofn sticks and an instrument. Each stick is characterized by its lengthli.
Ilya decided to make a rectangle from the sticks. And due to his whim, he decided to make rectangles in such a way that maximizes their total area. Each stick is used in making at most one rectangle, it is possible that some of sticks remain unused. Bending sticks is not allowed.
Sticks with lengths a1,a2, a3 and a4 can make a rectangle if the following properties are observed:
- a1 ≤ a2 ≤ a3 ≤ a4
- a1 = a2
- a3 = a4
A rectangle can be made of sticks with lengths of, for example, 3 3 3 3 or 2 2 4 4. A rectangle cannot be made of, for example, sticks5 5 5 7.
Ilya also has an instrument which can reduce the length of the sticks. The sticks are made of a special material, so the length of each stick can be reduced by at most one. For example, a stick with length5 can either stay at this length or be transformed into a stick of length4.
You have to answer the question — what maximum total area of the rectangles can Ilya get with a file if makes rectangles from the available sticks?
The first line of the input contains a positive integer n (1 ≤ n ≤ 105) — the number of the available sticks.
The second line of the input contains n positive integersli (2 ≤ li ≤ 106) — the lengths of the sticks.
The first line of the output must contain a single non-negative integer — the maximum total area of the rectangles that Ilya can make from the available sticks.
4 2 4 4 2
8
4 2 2 3 5
0
4 100003 100004 100005 100006
10000800015
解析
贪心。用cnt[i]表示长度为i的棍子的个数。从长度的max向min扫一遍。要形成长方形的边一定相等的边成对存在。又因为候选边越长越好,所以只有cnt[i]为奇数时我们才需要剪一根棍子(因为剩一根棍子没法配对)。可是为什么必须cnt[i-1]>0才剪呢?如果cnt[i-1]==0剪了也没有与之配对的棍子,并且担心同一根棍子被重复地剪。最后答案统计仍然是贪心,要形成尽量大的矩形面积,就要用尽量长的长和宽。
#include<cstdio>
#include<algorithm>
using namespace std;
int N,stick,cnt[1000010];
int main()
{
//freopen("C.in","r",stdin);
scanf("%d",&N);
int up=0,down=0x3f3f3f3f;
for(int i=1;i<=N;i++)
{
scanf("%d",&stick);
cnt[stick]++;
up=max(up,stick);
down=min(down,stick);
}
for(int i=up;i>=down;i--)
{
if(i>down && (cnt[i]&1) && cnt[i-1]) cnt[i]--,cnt[i-1]++;
cnt[i]=cnt[i]>>1;
}
//printf("%d %d\n",down,up);
//for(int i=down;i<=up;i++) printf("%d ",cnt[i]);puts("");
long long sum=0,remain=0;
for(int i=up;i>=down;i--)
{
if(cnt[i] && remain) {sum+=remain*i;cnt[i]--;remain=0;}
sum+= (cnt[i]>>1)*(long long)i*i;
if(cnt[i]&1) remain=i;
}
printf("%I64d\n",sum);
return 0;
}