Loading

Codeforces Round #611 (Div. 3) E

Oh, New Year. The time to gather all your friends and reflect on the heartwarming events of the past year...

nn friends live in a city which can be represented as a number line. The ii -th friend lives in a house with an integer coordinate xixi . The ii -th friend can come celebrate the New Year to the house with coordinate xi1xi−1 , xi+1xi+1 or stay at xixi . Each friend is allowed to move no more than once.

For all friends 1xin1≤xi≤n holds, however, they can come to houses with coordinates 00 and n+1n+1 (if their houses are at 11 or nn , respectively).

For example, let the initial positions be x=[1,2,4,4]x=[1,2,4,4] . The final ones then can be [1,3,3,4][1,3,3,4] , [0,2,3,3][0,2,3,3] , [2,2,5,5][2,2,5,5] , [2,1,3,5][2,1,3,5] and so on. The number of occupied houses is the number of distinct positions among the final ones.

So all friends choose the moves they want to perform. After that the number of occupied houses is calculated. What is the minimum and the maximum number of occupied houses can there be?

Input

The first line contains a single integer nn (1n21051≤n≤2⋅105 ) — the number of friends.

The second line contains nn integers x1,x2,,xnx1,x2,…,xn (1xin1≤xi≤n ) — the coordinates of the houses of the friends.

Output

Print two integers — the minimum and the maximum possible number of occupied houses after all moves are performed.

 

大意是有n个点,每个点有一定数量的人,一个点的人可以移动到这个点的位置xi左右两边或选择不移动(xi+1 xi-1 xi)。让求这些人经过移动(或不移动)后最多能占据多少个不同的点,最少能占据多少个不同的点。

最少点的情况比较简单(但做的时候想麻烦了 ,只需要遍历一遍数组,遇到没有人的地方直接跳过,有人的地方计数器++然后i+=2。因为这是从左到右统计的,基于贪心的思想,如果i位置有人,i+1位置的所有人一起移动到i位置显然比其他方案更优。

最多点的情况稍微复杂一点。我用一个vis数组记录了点的占据情况。

  (1)如果一个点有三个人以上,可以把这三个人分到i-1,i,i+1的位置;

  (2)如果一个点有两个人:

      [1] i-1没有人:分到i-1和i

      [2]其他情况:分到i和i+1

  (3)一个点只有一个人:

      [1]i-1没有人:分到i-1

      [2]i-1有人,i没有人:分到i

      [3]其他情况:分到i+1

“分到xx”即为vis数组的对应位置打上标记。最后统计打了标记的位置即可。

#include <bits/stdc++.h>
using namespace std;
int n;
struct people
{
    int pos;
    int cnt;
 }p[200005];
 int vis[200005]={0};
int solvemin()
{
    int ans=0;
    int i;
    for(i=1;i<=n;i++)
    {
        if(p[i].cnt==0)continue;
        ans++;
        i+=2;
    }
    return ans;    
}
int solvemax()
{
    int i;
    int ans=0;
    for(i=1;i<=n;i++)
    {
        if(p[i].cnt>=3)
        {
            vis[i-1]++;
            vis[i]++;
            vis[i+1]++;
        }
        else if(p[i].cnt==2)
        {
            if(!vis[i-1])
            {
                vis[i-1]++;
                vis[i]++;
            }
            else
            {
                vis[i]++;
                vis[i+1]++;
            }
        }
        else if(p[i].cnt==1)
        {
            if(!vis[i-1])
            {
                vis[i-1]++;
            }
            else if(!vis[i])
            {
                vis[i]++;
            }
            else vis[i+1]++;
        }
        else continue;
    }
    for(i=0;i<=n+1;i++)
    {
        if(vis[i])ans++;
    }
    return ans;
}
int main()
{
    cin>>n;
    int i;
    for(i=0;i<=n;i++)
    {
        p[i].pos=i;
        p[i].cnt=0;
    }
    for(i=1;i<=n;i++)
    {
        int temp;
        scanf("%d",&temp);
        p[temp].cnt++;
    }
    int mmin=solvemin();
    int mmax=solvemax();
    cout<<mmin<<' '<<mmax;
    return 0;
}

 

 

 
 
 
 
 
 
 
posted @ 2020-01-22 12:18  脂环  阅读(141)  评论(0编辑  收藏  举报