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