//成段更新,不必更新到底
//id记录的是节点被编号为id人的海报遮住
//墙的长度很长,在建树时,应以海报贴的最右边为准,不然会MLE
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 10005
int n,m,t,sum,p;
struct TNode
{
int l,r,id;
} node[8*N];
int lx[N],rx[N];
int lr[2*N];
bool vis[N];
void build(int root,int l,int r)
{
node[root].id=0;
node[root].l=l,node[root].r=r;
if(l==r) return ;
int mid=(l+r)>>1,p=root<<1;
build(p,l,mid);
build(p+1,mid+1,r);
}
void insert(int root,int l,int r,int id)
{
int mid,p=root<<1;
if(node[root].l==l&&node[root].r==r)
{
node[root].id=id;
return ;
}
if(node[root].id>0)
{
node[p].id=node[root].id;
node[p+1].id=node[root].id;
node[root].id=0;
}
mid=(node[root].l+node[root].r)>>1;
if(r<=mid) insert(p,l,r,id);
else if(l>mid) insert(p+1,l,r,id);
else
{
insert(p,l,mid,id);
insert(p+1,mid+1,r,id);
}
}
void query(int root,int l,int r)
{
int mid,p;
mid=(node[root].l+node[root].r)>>1;
p=root<<1;
if(node[root].id>0)
{
if(vis[node[root].id]==0)
{
sum++;
vis[node[root].id]=1;
}
return ;
}
if(r<=mid) query(p,l,r);
else if(l>mid) query(p+1,l,r);
else
{
query(p,l,mid);
query(p+1,mid+1,r);
}
}
int find(int x)
{
int l=0,r=p-1,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(lr[mid]==x) return mid;
else if(lr[mid]<x) l=mid+1;
else r=mid-1;
}
return -1;
}
int main()
{
int l,i,r,k;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(vis,0,sizeof(vis));
for(k=1,p=0; k<=n; k++)
{
scanf("%d%d",&lx[k],&rx[k]);
lr[p++]=lx[k];
lr[p++]=rx[k];
}
sort(lr,lr+p);
k=p;
for(i=1,p=0;i<k;i++)
{
if(lr[i]!=lr[p]) lr[++p]=lr[i];
}
p++;
build(1,1,p);
for(i=1;i<=n;i++)
{
if(lx[i]>rx[i]) swap(lx[i],rx[i]);
int l=find(lx[i]),r=find(rx[i]);
insert(1,l+1,r+1,i);
}
sum=0;
query(1,1,p);
printf("%d\n",sum);
}
return 0;
}
poj2528---线段树
最新推荐文章于 2019-12-02 14:12:38 发布