题目大意:
就跟在电线杆上帖小广告一样,先贴的总是会被后帖的给覆盖了,现在要求你求出当最后一张小广告贴上去之后还剩多少没有被完全覆盖。
解题思路:
这个思路还是线段树的思路,但是由于数据范围太大了,所以要做离散化处理,要用到的其实就是一些个左端点啊,右端点,以及为了防止漏掉中间断层而添加的中间的点。
具体思路看代码:
#include<stdio.h>
#include<set>
#include<string.h>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define N 20009
using namespace std;
int st[N<<2],ed[N<<2];//保存端点的
int temp[N<<2];//离散化的点
set<int>sett;//中间处理的时候用
bool visit[N<<2],use[N<<3];//标记
void build(int rt,int l,int r)//建树也就是清空,可以用memset取而代之
{
use[rt]=false;
if(l==r)
return ;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
int ans=0;
void update(int rt,int l,int r,int a,int b,int c)//查找并更新
{
if(use[rt])
return ;
if(temp[l]>=a&&temp[r]<=b)
{
use[rt]=true;
if(!visit[c])
{
ans++;
visit[c]=true;
}
return ;
}
int mid=(l+r)>>1;
if(b<=temp[mid])
update(lson,a,b,c);
else if(a>temp[mid])
update(rson,a,b,c);
else
{
update(lson,a,temp[mid],c);//向左边缩小范围
update(rson,temp[mid+1],b,c);//。。。
}
if(use[rt<<1]&&use[rt<<1|1])
use[rt]=true;
}
int main()
{
int t;
scanf("%d",&t);
int n,i,a,b,nn;
while(t--)
{
sett.clear();
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&st[i],&ed[i]);
}
sett.insert(st,st+n);
sett.insert(ed,ed+n);
set<int>::const_iterator ir,jr;
jr=sett.begin();
jr++;
i=0;
for(ir=sett.begin();jr!=sett.end();ir++,jr++)
{
if(*ir+1!=*jr)
temp[i++]=*ir+1;
}
sett.insert(temp,temp+i);
i=0;
for(ir=sett.begin();ir!=sett.end();ir++)
temp[++i]=*ir;
nn=i;
build(1,1,nn);
memset(visit,false,sizeof(visit));
ans=0;
for(i=n-1;i>=0;i--)
{
update(1,1,nn,st[i],ed[i],i);
}
printf("%d\n",ans);
}
}
这个时间复杂度有点大。。。待优化。
继续。。。。
去掉Set和memset,从500多优化到63,内存从2000多优化到779,恩,看来STL库不能随便用啊。。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define N 20009
using namespace std;
int st[N<<2],ed[N<<2];
int temp[N<<3];
bool visit[10000009],use[N<<3];
void build(int rt,int l,int r)
{
use[rt]=false;
if(l==r)
return ;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
int ans=0;
void update(int rt,int l,int r,int a,int b,int c)
{
if(use[rt])
return ;
if(temp[l]>=a&&temp[r]<=b)
{
use[rt]=true;
if(!visit[c])
{
ans++;
visit[c]=true;
}
return ;
}
int mid=(l+r)>>1;
if(b<=temp[mid])
update(lson,a,b,c);
else if(a>temp[mid])
update(rson,a,b,c);
else
{
update(lson,a,temp[mid],c);
update(rson,temp[mid+1],b,c);
}
if(use[rt<<1]&&use[rt<<1|1])
use[rt]=true;
}
int main()
{
int t;
scanf("%d",&t);
int n,i,nn,j;
while(t--)
{
scanf("%d",&n);
j=0;
for(i=0;i<n;i++)
{
scanf("%d%d",&st[i],&ed[i]);
temp[j++]=st[i];
temp[j++]=ed[i];
}
nn=j;
sort(temp,temp+nn);
for(i=0,j=0;j<nn;j++){
if(temp[i]!=temp[j+1])
temp[++i]=temp[j+1];
}
nn=i+1;
for(i=nn-2,j=nn-1;i>=0;i--,j--)
{
if(temp[i]+1!=temp[j])
temp[nn++]=temp[i]+1;
}
temp[nn]=0;
sort(temp,temp+nn+1);
build(1,1,nn);
for(i=0;i<n;i++)
visit[i]=false;
ans=0;
for(i=n-1;i>=0;i--)
{
update(1,1,nn,st[i],ed[i],i);
}
printf("%d\n",ans);
}
}
end...