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

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;
 
}








你可能感兴趣的:(codeforces#331-C - Wilbur and Points-set/贪心乱搞)