CodeForces 128D Numbers 贪心 或 YY

来源:互联网 发布:全网通是什么网络制式 编辑:程序博客网 时间:2024/04/30 01:04

题目大意:

就是给你n个正整数数(3 <= n <= 10^5), 每个正整数数都不超过10^9, 现在问是否能将这n个数排成一个环, 使得换上相邻两个数的差都是1


大致思路:

我的思路就是YY的..方法见代码注释

另外有个贪心的做法:

排序后每次去一个数, 如果这个数num有剩余的num - 1存在就接上num - 1, 否则接上num + 1, 最后判是否首尾连接即可

我的做法当时YY出来的, 后来和贪心比较了一下发现性质有明显的相似之处


代码如下:

Result  :  Accepted     Memory  :  500 KB     Time  :  92 ms

/* * Author: Gatevin * Created Time:  2015/2/14 14:23:44 * File Name: Mononobe_Mitsuki.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;int n;int num[100010];bool vis[100010];/* * 我的想法明显具有YY性质 * 首先将n个数排序, 然后从最小的开始找严格单调递增+1的序列到最大的数 * 然后在回来找一次严格-1序列, 这样形成一个环包含1次最小和最大值, 大小为(max - min)*2 * 然后对于剩下的数, 因为环中有任意的(a, a + 1)节点相连 * 所以如果两个相邻的数对于比如对于出一对(k, k + 1)那么可以插入环中的..k - 1, k, k + 1..序列中变成 * ..k - 1, k, k + 1, k, k + 1..这样,同时没有破环存在所有(a, a + 1)插入点 * 如果在构造初始环之后剩下的数都可以分成两两一组, 每组两个数差为1则可行, 否则不可行 */int main(){    scanf("%d", &n);    for(int i = 1; i <= n; i++)        scanf("%d", num + i);    sort(num + 1, num + n + 1);    memset(vis, 0, sizeof(vis));    vis[1] = 1;    int now = num[1];    for(int i = 2; i <= n; i++)//从最小到最大的单调递增+1链    {        if(!vis[i] && abs(num[i] - now) >= 2)//找不到这个链,有断点        {            printf("NO\n");            return 0;        }        if(!vis[i] && num[i] == now + 1)        {            vis[i] = 1;            now = num[i];        }    }    for(int i = n; i >= 2 && num[i] != num[1]; i--)//回来成环    {        if(vis[i]) continue;        if(abs(num[i] - now) >= 2)//元素不能成环,有断点        {            printf("NO\n");            return 0;        }        if(num[i] == now - 1)        {            vis[i] = 1;            now = num[i];        }    }    if(now != num[1] + 1)//回链不能和最小的链接    {        printf("NO\n");        return 0;    }    now = -1;    int cnt = 0;    for(int i = 1; i <= n; i++)//寻找两两相邻一组    {        if(vis[i]) continue;        vis[i] = 1;        if(now == -1)        {            now = num[i];            cnt = 1;            continue;        }        if(num[i] == now)        {            cnt++;            continue;        }        if(num[i] == now + 1)        {            if(cnt > 1)                cnt--;            else            {                if(cnt == 1)                {                    cnt = 0;                    now = -1;                }            }        }        if(num[i] == now + 2)//now有剩余时断开了,找不到now + 1        {            printf("NO\n");            return 0;        }    }    if(now != -1)//有剩余的now        printf("NO\n");    else        printf("YES\n");    return 0;}


0 0