题目思路:
1:Alice 按宽度w小优先,高度h小次优先的顺序拿出卡片,从Bob的宽度小于w的卡片中贪心覆盖高度h最接近h并且小于h的卡片。
2:卡片数量大,所以只能在n*logn时间复杂度内,每次Alice拿出宽度w的卡片,我们就把Bob中宽度小于w的所有卡片提供一个满足(1)条件的卡片,那么我们可以用线段树存放,线段节点存放该高度空间中的Bob卡片张数;
3:如何告诉选择一个” Bob的宽度小于w的卡片中贪心覆盖高度h最接近h并且小于h的卡片 “ ,利用线段树,找到h所在叶子节点,找到离该叶子节点左边的最接近的一个非零叶子节点即可。
————————————————————————————
注意题目说卡片不能旋转,真心坑爹呀!!!!花了我几个小时调试
————————————————————————————
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4268
下面是我的代码
#include<stdio.h>
#include<algorithm>
#define MAX 220001
int Alice[MAX][2];
int Bob[MAX][2];
int height[MAX], num;
int hash[MAX],list[MAX];
int n;
struct Node
{
int l, r;
int num;
}node[MAX * 4];
int cmp1(const void *a, const void *b)
{
int *aa = (int *)a;
int *bb = (int *)b;
if(aa[0] > bb[0])
{
return 1;
}
else if(aa[0] < bb[0])
{
return -1;
}
else
{
return aa[1] - bb[1];
}
return 1;
}
int cmp2(const void *a, const void *b)
{
return *((int *)a) - *((int *)b);
}
int insert(int x)
{
int xx = x % MAX;
while(hash[xx] != 0 && list[xx] != x)
{
xx = (xx + 1) % MAX;
}
if(hash[xx] == 0)
{
hash[xx] = 1;
list[xx] = x;
return 1;
}
return 0;
}
int build(int left, int right, int pre)
{
node[pre].l = left;
node[pre].r = right;
node[pre].num = 0;
if(left == right )
return 0;
int mid = (left + right) / 2;
build(left, mid, pre * 2);
build(mid + 1, right, pre * 2 + 1);
return 0;
}
int insert(int x, int pre)
{
if(node[pre].l == node[pre].r)
{
node[pre].num ++;
return 0;
}
int mid = (node[pre].l + node[pre].r) / 2;
if(x <= height[mid])
{
insert(x, pre * 2);
}
else
insert(x, pre * 2 + 1);
node[pre].num = node[pre * 2].num + node[pre * 2 + 1].num;
return 0;
}
int find(int x, int pre)
{
if(node[pre].l == node[pre].r)
{
return pre;
}
int mid = (node[pre].l + node[pre].r) / 2;
if(x >= height[mid + 1])
return find(x, pre * 2 + 1);
else
return find(x, pre * 2);
return 0;
}
int cover(int pre)
{
if(node[pre].num != 0)
{
node[pre].num --;
}
else
{
int father = pre / 2;
if(father == 0)
return 0;
while(!(father * 2 != pre && node[father * 2].num != 0))
{
pre /= 2;
father = pre / 2;
if(father == 0)
return 0;
}
pre --;
while(node[pre].l != node[pre].r)
{
if(node[pre * 2 +1].num != 0)
{
pre = pre * 2 + 1;
}
else
pre = pre * 2;
}
node[pre].num --;
}
pre /= 2;
while(pre != 0)
{
node[pre].num = node[pre * 2].num + node[pre * 2 + 1].num;
pre /= 2;
}
return 1;
}
int count()
{
int a, b;
int c = 0;
int front = 0;
for(a = 1; a <= n; a ++)
{
while(front + 1 <= n && Bob[front + 1][0] <= Alice[a][0])
{
insert(Bob[++front][1], 1);
}
int pre = find(Alice[a][1], 1);
if(cover(pre))
{
c ++;
}
}
return c;
}
int main()
{
int cases, i;
scanf("%d",&cases);
while(cases --)
{
scanf("%d",&n);
num = 0;
memset(hash, 0, sizeof(hash));
for(i = 1; i <= n; i ++)
{
scanf("%d%d", &Alice[i][0], &Alice[i][1]);
if(insert(Alice[i][1]))
height[++num] = Alice[i][1];
}
qsort(Alice + 1, n, sizeof(int) * 2, cmp1);
for(i = 1; i <= n; i ++)
{
scanf("%d%d", &Bob[i][0], &Bob[i][1]);
if(insert(Bob[i][1]))
height[++num] = Bob[i][1];
}
qsort(Bob + 1, n, sizeof(int) * 2, cmp1);
qsort(height + 1, num, sizeof(int), cmp2);
build(1, num, 1);
printf("%d\n", count());
}
return 0;
}