输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第1行为两个整数N和L,分别表示总共贴上的海报数量和宣传栏的宽度。
每组测试数据的第2-N+1行,按照贴上去的先后顺序,每行描述一张海报,其中第i+1行为两个整数a_i, b_i,表示第i张海报所贴的区间为[a_i, b_i]。
对于100%的数据,满足N<=10^5,L<=10^9,0<=a_i<b_i<=L。
输出
对于每组测试数据,输出一个整数Ans,表示总共有多少张海报能被看到。
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
struct node{
int flag; // 海报编号
int l,r; //左端点,右端点
};
vector<int> v; //用于离散化
int pt_x[100005],pt_y[100005]; //记录区间端点
node tree[100000*40]; //线段树
bool use[100005*2+10]; //记录能看到的海报
int ans; //能看到的海报数
//获得离散值
int getID(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
//建树
void build(int root,int l,int r){
tree[root].flag = 0;
tree[root].l = l;
tree[root].r = r;
if(l+1==r) return; //到达叶子结点
int mid = (l+r)/2;
build(root*2,l,mid);
build(root*2+1,mid,r);
}
void update(int l,int r,int root,int x){
if(tree[root].l==l&&tree[root].r==r){
tree[root].flag = x;
return;
}
if(tree[root].l+1>=tree[root].r) return; //到达叶子结点
if(tree[root].flag){ //如果当前区间贴上了海报,其子区间也要更新
tree[root*2+1].flag = tree[root*2].flag = tree[root].flag;
tree[root].flag = 0;
}
int mid = (tree[root].l+tree[root].r)/2;
if(l>mid) //待更新区间在当前区间的左半边
update(l,r,root*2+1,x);
else if(r<=mid) //待更新区间在当前区间的右半边
update(l,r,root*2,x);
else{
//
update(l,mid,root*2,x);
update(mid,r,root*2+1,x);
}
}
void query(int root){
if(tree[root].flag&&!use[tree[root].flag]){
ans++;
use[tree[root].flag] = 1;
return;
}
if(tree[root].l+1>=tree[root].r) return; //到达叶子结点
if(!use[tree[root].flag]){
query(root*2);
query(root*2+1);
}
}
int main(int argc, char** argv) {
int n,L;
v.clear();
memset(tree,0,sizeof(tree));
scanf("%d %d",&n,&L);
for(int i=0;i<n;i++){
scanf("%d %d",&pt_x[i],&pt_y[i]);
v.push_back(pt_x[i]);
v.push_back(pt_y[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
int N = v.size();
build(1,1,N);
for(int i=0;i<n;i++){
update(getID(pt_x[i]),getID(pt_y[i]),1,i+1);
}
ans = 0;
memset(use,0,sizeof(use));
query(1);
printf("%d\n",ans);
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/4334084/blog/3829005