5029: 贴小广告
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 161 Solved: 101
[ Submit][ Status][ Discuss]
Description
现在有一堵墙,墙上分为若干个单元。接下来会来n个人在墙上贴小广告。每次每个人选择墙上连续一段的单元贴上自己公司与众不同的小广告。因为小广告可能会出现被覆盖的情况,由于公司之间存在竞争,后贴广告的人想让别人看不见前面公司的广告,所以会将前面的广告完全覆盖。因此对于墙上的某个单元上贴的小广告中只有贴的最晚的能被看见。现在想要知道n个人依次贴完后,墙上共能看到多少种小广告?
Input
输入文件第一行有一个整数 n。
接下来 n 行每行 2 个整数 li、ri,表示这个人在第li个单元到第ri个单元贴了小广告。
1 <= n,m <= 10^5 , 1<=li<=ri<=10^7
Output
输出所有人贴完后墙上能看到多少种小广告?
Sample Input
5
1 4
2 6
8 10
3 4
7 10
Sample Output
4
倒过来处理,用线段树维护当前区间是否有小广告
离散化的时候注意坑!
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct
{
int x;
int y;
}Line;
Line s[210005];
int n, flag, ans, tre[544444], dtt[203333] = {-1};
void Create(int l, int r, int x);
void Update(int l, int r, int x, int a, int b);
int Bsech(int l, int r, int t);
int main(void)
{
int T, i, m, k, ans, a, b;
ans = n = 0;
scanf("%d", &m);
for(i=1;i<=m;i++)
{
scanf("%d%d", &s[i].x, &s[i].y);
dtt[++n] = s[i].x, dtt[++n] = s[i].y;
}
sort(dtt+1, dtt+n+1);
k = 0;
for(i=1;i<=n;i++)
{
if(dtt[i]!=dtt[i-1])
dtt[++k] = dtt[i];
}
n = k;
for(i=1;i<=n;i++)
{
if(dtt[i]+1!=dtt[i+1])
dtt[++k] = dtt[i]+1;
}
n = k;
sort(dtt+1, dtt+n+1);
Create(1, n, 1);
for(i=m;i>=1;i--)
{
a = Bsech(1, n, s[i].x);
b = Bsech(1, n, s[i].y);
flag = 0;
Update(1, n, 1, a, b);
if(flag==1)
ans++;
}
printf("%d\n", ans);
return 0;
}
int Bsech(int l, int r, int t)
{
int m;
m = (l+r)/2;
if(t==dtt[m])
return m;
if(t<dtt[m])
return Bsech(l, m-1, t);
return Bsech(m+1, r, t);
}
void Create(int l, int r, int x)
{
int m;
if(l==r)
{
tre[x] = 1;
return;
}
m = (l+r)/2;
Create(l, m, x*2);
Create(m+1, r, x*2+1);
tre[x] = tre[x*2]+tre[x*2+1];
}
void Update(int l, int r, int x, int a, int b)
{
int m;
if(l>=a && r<=b && tre[x]==0)
return;
if(l==r && l>=a && l<=b)
{
tre[x] = 0;
flag = 1;
return;
}
m = (l+r)/2;
if(a<=m)
Update(l, m, x*2, a, b);
if(b>=m+1)
Update(m+1, r, x*2+1, a, b);
tre[x] = tre[x*2]+tre[x*2+1];
}