定义一个二维点集的美观数列a[]:对任意的a[i], 使得集合里面所有满足0 <= x[j] < x[i] && 0 <= y[j] < y[i]的a[j] <= a[i]。
题意:给定一个二维点集x[], y[]和一个序列w[],问你是否存在一个美观序列a[]使得对任意的i都唯一对应——a[i] = y[i] - x[i] = w[j]。若存在输出任意一组序列,反之输出-1。
好麻烦的题,思路怎么说呢。。。就是贪心思维胡搞吧,总之sort被用的清新脱俗。
思路:首先判断是否存在一个最佳的(最可能是一个美观序列)序列b[]使得,b[i] = y[i] - x[i] = w[j]。再判断序列b[]是否为关于二维点集的一个美观序列。
第一步:直接求出二维点集的y[] - x[]的val值,把该信息与对应的id以及x、y值用num1[]存储起来,然后贪心的排序,策略是先按val升序,再按x升序,最后按y升序(调换x和y的顺序应该是不会错的)。对给出的序列w[],记录元素的在序列中的id值和val,这些可以用num2[]存储,然后贪心排序,不同的是先按val升序,再按id值升序。最后从头到尾扫一遍,并记录序列b[]。
第二步:建立在序列b[]存在的前提下。我们经过上一步求出的b[]是最可能满足美观序列的,所以只需要更新出初始序列num1,num2,然后根据w[]的先后(序列b[]是按w[]的输入顺序求出的),判断num1(最初的二维点集)相邻的b[i]和b[i-1]之间是否满足x[b[i]] > x[b[i-1]] || y[b[i]] > y[b[i-1]]。
AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-4
#define MAXN (200000+10)
#define MAXM (1000000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 100000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
using namespace std;
struct Node{
int x, y, val, id, rec;
};
Node num1[MAXN], num2[MAXN];
bool cmp(Node a, Node b)
{
if(a.val != b.val)
return a.val < b.val;
else if(a.x != b.x)
return a.x < b.x;
else
return a.y < b.y;
}
bool cmp1(Node a, Node b)
{
if(a.val != b.val)
return a.val < b.val;
else
return a.id < b.id;
}
bool cmp2(Node a, Node b){
return a.id < b.id;
}
int main()
{
int n; Ri(n);
for(int i = 0; i < n; i++)
{
Ri(num1[i].x); Ri(num1[i].y);
num1[i].val = num1[i].y - num1[i].x;
num1[i].id = i;
}
sort(num1, num1+n, cmp);
for(int i = 0; i < n; i++)
{
Ri(num2[i].val);
num2[i].id = i;
}
sort(num2, num2+n, cmp1);
bool flag = true;
for(int i = 0; i < n; i++)
{
if(num1[i].val != num2[i].val)
{
flag = false;
break;
}
else
num2[i].rec = num1[i].id;
}
if(flag)
{
sort(num2, num2+n, cmp2);
sort(num1, num1+n, cmp2);
for(int i = 1; i < n; i++)
{
if(!(num1[num2[i].rec].x > num1[num2[i-1].rec].x || num1[num2[i].rec].y > num1[num2[i-1].rec].y))
{
flag = false;
break;
}
}
if(flag)
{
printf("YES\n");
for(int i = 0; i < n; i++)
printf("%d %d\n", num1[num2[i].rec].x, num1[num2[i].rec].y);
}
else
printf("NO\n");
}
else
printf("NO\n");
return 0;
}