您的位置:首页 > 其它

codeforces#331-C - Wilbur and Points-set/贪心乱搞

2016-04-03 01:52 337 查看
http://codeforces.com/contest/596/problem/C

题意:

给n个点,保证只要点(x,y)出现了,所有x'<=x&&y'<=y的点(x',y')都会出现在输入中。

现在要求给n个点编号,要求满足一个条件【美丽序】:

对点(x,y),只要有x'>=x&&y'>=y ,则(x',y')的编号一定不小于点(x,y)的编号。

定义一个点的value=y-x,

并且最后给出一个w[]数组,要求你给n个点编号后,使得每个编号为i的点的权值等于w[i]。

如果不存在方案 输出-1

-------------------------------------

思路:

开一个二维vector<> mp

首先我们考虑编号问题,我们先把每个点存到mp[ valuie[i] ], 显然value相同的点一定在一个x=y+a的直线上,因此只需要按x排序就可以确保这些编号都是满足【美丽序】

那么我们把给出的w[]数组中 所有w[i]==x,的节点编号都 拿出来(升序),显然这些编号对应着mp【x】中的所有节点 应该编的号。

因此 编号过程完成了,编号结束后,我们的编号方式一定和给出w[]数组的权值一样。

并且如果存在一个满足美丽序的答案,我们这个一定是满足的。

因此我们只需要检测一下编号结果是否还是满足美丽序就好了

【由于题目的几个限定条件只需要判断,ans[i].x<=ans[i-1].x&&ans[i].y<=ans[i-1].y,则NO】

【判断最后是否合法还有一种方案,每次把编号了的点加入一个集合就是当要编号点(x,y)时,直接在集合里找是否存在(x-1,y),(x,y-1),如果存在则说明所有x'<=x&&y'<=y的点(x',y')都已经被编号了,那么对于(x,y)编号为当前值一定不会和前面的编号方案产生冲突】

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;
int min(int a,int b)
{return a<b?a:b;}
int max(int a,int b)
{return a>b?a:b;}
struct node
{
int x,y;
int w,id;
node(){}
node(int a,int b)
{x=a;y=b;}
};
node tm[100005];
vector<node> mp[100005+100005];
bool cmp(node a,node b)
{return a.x<b.x;}
bool cmp2(node a,node b)
{return a.id<b.id;}
int ww[100005];
node ans[100005];

vector<int> idx[100005+100005];
int main()
{

int n,i,j;
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d%d",&tm[i].x,&tm[i].y);
int w=tm[i].y-tm[i].x;
tm[i].w=w;
mp[w+100000].push_back(tm[i]);	//得到权值为w的所有坐标
}

for (i=1;i<=n;i++)		//得到ww[i]的所有id(升序)
{
scanf("%d",&ww[i]);
idx[ww[i]+100000].push_back(i);
}

for (i=0;i<=200000;i++)		//排序(按美丽序)
sort(mp[i].begin(),mp[i].end(),cmp);
int flag=0;
for (i=1;i<=n;i++)
{
int x=ww[i];
int sz=idx[x+100000].size();
int check=mp[x+100000].size();
if (sz!=check)			//检查数量是否一致
{
flag=1;break;
}
for (j=0;j<mp[x+100000].size();j++)		//按美丽序依次填上编号
{
//	printf("(%d,%d)--%d\n",mp[x+100000][j].x,mp[x+100000][j].y,idx[x+100000][j]);
mp[x+100000][j].id=idx[x+100000][j];
}
}
if (flag)
{
printf("NO\n");return 0;
}

int ok=0;
for (i=0;i<=200000;i++)		//整理答案
{
for (j=0;j<mp[i].size();j++)
ans[++ok]=mp[i][j];
}
sort(ans+1,ans+1+ok,cmp2);		//按编号id排序
flag=0;
for (i=1;i<=n;i++)
{
if (ww[i]!=ans[i].w)		//判断方案可行
{
flag=1;break;
}
}
for (i=2;i<=n;i++)	//判断方案可行(满足美丽序)
{
if (ans[i].x<=ans[i-1].x&&ans[i].y<=ans[i-1].y) {flag=1;break;}
}

if (flag)
{
printf("NO\n");return 0;
}
else
{
printf("YES\n");
for (i=1;i<=n;i++)
printf("%d %d\n",ans[i].x,ans[i].y);
}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: