输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第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; }