G也不难,但是做对的人不多。
如果范围不是1千万,是1百万或者更小,我们可以用标号法,不断覆盖数组上的值。
这道题是1千万,显然要有一个比较好的数据结构,我选用的是一个链表,其中为了加快删除结点速度,我用双向链表。
每贴一张海报,看看是否与前面的海报发生覆盖事件,大概有3种情况
覆盖了一张海报的左边或右边,修改下原来的海报的尺寸
覆盖了海报的中间,海报分为左边右边两部分,那么要新增一个结点,把原来的海报修改为海报的左边,新增海报右边部分到队尾。
完全覆盖了一张海报,删除原来海报
最后做一个统计
我的算法还是比较慢的,有更快的思路请帖出来共享一下
#include<stdio.h>
struct node
{
int l,r,up,next,num;
} post[100000];
int head,total,tail;
void add(int l,int r,int num)
{
total++;
post[total].l=l;
post[total].r=r;
post[total].num=num;
post[total].up=tail;
post[total].next=0;
post[tail].next=total;
tail=total;
}
void del(int k)
{
int up;
if(k==head)
head=post[k].next;
else if(k==tail)
tail=post[k].up;
up=post[k].up;
post[up].next=post[k].next;
up=post[k].next;
post[up].up=post[k].up;
}
int main()
{
int i,j,k,n,m,num[10000],a,b,l,r;
head=1;
freopen(\"in.txt\",\"r\",stdin);
scanf(\"%d\",&n);
while(n--)
{
scanf(\"%d\",&m);
for (i=0;i<=m;i++) num=0;
scanf(\"%d %d\",&a,&b);
head=1;total=1;tail=1;
post[1].up=0;post[1].next=0;
post[1].l=a;post[1].r=b;
post[1].num=1;
num[1]=1;
for (i=1;i<m;i++)
{
scanf(\"%d %d\",&a,&b);
j=head;
k=tail;
add(a,b,i+1);
num[i+1]++;
while(j<=k)
{
l=post[j].l;
r=post[j].r;
if(a<=l)
{
if(b<r)
{
if(b>=post[j].l)
post[j].l=b+1;
}else
{
num[post[j].num]--;
del(j);
}
}else if(a<=r)
{
if(b>=r)
{
post[j].r=a-1;
}else
{
add(b+1,r,post[j].num);
num[post[j].num]++;
post[j].r=a-1;
}
}
j=post[j].next;
}//while
}//for
k=0;
for (i=1;i<=m;i++) if(num>0) k++;
printf(\"%d\\n\",k);
}
return 0;
} |