2012 ACM ICPC 长春网络赛B Alice And Bob 线段树的延伸利用

题目思路:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值