题目链接:http://poj.org/problem?id=2528
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 43201 | Accepted: 12591 |
Description
Input
Output

Sample Input
1 5 1 4 2 6 8 10 3 4 7 10
Sample Output
4
Source
今天又把这道题做了一遍~离散化参考自http://www.cnblogs.com/vongang/archive/2011/08/10/2133869.html思路:典型的线段树,区间更新,然后递归查询即可,但是这题输入的数据 1 <= li <= ri <= 10000000.
数据太大,直接建树肯定会MLE,所以离散化一下,也就是将2*n个数映射在1~2*n之间~~~
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <cstdio>
#include <cmath>
#include <algorithm>
const int N=20000+100;
using namespace std;
int cnt;
struct node
{
int l,r,cover;
}st[N*4];
struct node1
{
int num; // 存放端点的值
int id; // 存放端点的位置
}po[N*2];
bool cmp(node1 a,node1 b)
{
return a.num<b.num;
}
int f[N][2],flag[N];
void build(int v,int l,int r)
{
st[v].l=l;
st[v].r=r;
st[v].cover=0;
if(l==r)return;
int mid=(l+r)/2;
build(2*v,l,mid);
build(2*v+1,mid+1,r);
}
void update(int v,int l,int r,int d)
{
if(st[v].l==l&&st[v].r==r)
{
st[v].cover=d;
return;
}
if(st[v].cover>0)
{
st[2*v].cover=st[v].cover;
st[2*v+1].cover=st[v].cover;
st[v].cover=0;
}
int mid=(st[v].l+st[v].r)/2;
if(r<=mid)update(2*v,l,r,d);
else if(l>mid)update(2*v+1,l,r,d);
else
{
update(2*v,l,mid,d);
update(2*v+1,mid+1,r,d);
}
}
void getsum(int v)
{
if(st[v].cover)
{
if(!flag[st[v].cover])
{
cnt++;
flag[st[v].cover]=1;
}
return;
}
getsum(2*v);
getsum(2*v+1);
}
int main()
{
int T,n;
cin>>T;
while(T--)
{
scanf("%d",&n);
memset(f,0,sizeof(f));
memset(flag,0,sizeof(flag));
for(int i=1;i<=n;i++)
{
scanf("%d%d",&f[i][0],&f[i][1]);
po[2*i-1].num=f[i][0];//左端点的值
po[2*i-1].id=i; //标记为左端点
po[2*i].num=f[i][1]; //右端点的值
po[2*i].id=-1*i; //标记为右端点
}
sort(po+1,po+1+2*n,cmp);
int t=1,temp=po[1].num;
for(int i=1;i<=2*n;i++)
{
if(temp!=po[i].num)
{
t++;
temp=po[i].num;
}
if(po[i].id>0)
f[po[i].id][0]=t;
else
f[-1*po[i].id][1]=t;
}
build(1,1,t);
for(int i=1;i<=n;i++)
{
update(1,f[i][0],f[i][1],i);
}
cnt=0;
getsum(1);
printf("%d\n",cnt);
}
return 0;
}
原文地址:http://blog.csdn.net/liusuangeng/article/details/39524335