您的位置:首页 > 其它

CodeForces 128D Numbers 贪心 或 YY

2015-02-14 20:52 471 查看
题目大意:

就是给你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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息