線段樹+離散化poj2528
阿新 • • 發佈:2018-11-11
http://poj.org/problem?id=2528
題意是給你n個區間,後來的區間會覆蓋前面的區間,問你最後有多少區間沒有被完全覆蓋
由於r的最大值是10000000,所以先將資料進行離散化處理,把所有所有區間的l,r排序,離散化後在從後往前去覆蓋區間
如果該區間已經被覆蓋,則返回false
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct Point { int x;int id; } point[4*20005]; struct Tree { int l,r; int vis; } tree[4*20005]; bool cmp1(Point a,Point b) { return a.x<b.x; } bool cmp2(Point a,Point b) { if(a.id==b.id) { return a.x<b.x; } return a.id>b.id; } void PushUp(intrt) { tree[rt].vis=tree[2*rt].vis&&tree[2*rt+1].vis; } void bulid(int rt,int L,int R) { tree[rt].vis=0; tree[rt].l=L; tree[rt].r=R; if(tree[rt].l==tree[rt].r) { return; } int mid=(L+R)/2; bulid(2*rt,L,mid); bulid(2*rt+1,mid+1,R); } bool query(int rt,int L,int R) { if(tree[rt].vis) { return false; } if(tree[rt].l==L&&tree[rt].r==R) { tree[rt].vis=1; return true; } bool isok=false; int mid=(tree[rt].l+tree[rt].r)/2; if(R<=mid) { isok = query(2*rt,L,R); } else if(L>=mid+1) { isok = query(2*rt+1,L,R); } else { isok = query(2*rt,L,mid)|query(2*rt+1,mid+1,R); } PushUp(rt); return isok; } int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); for (int i=0; i<2*n ; i+=2 ) { scanf("%d %d",&point[i].x,&point[i+1].x); point[i].id=point[i+1].id=i; } sort(point,point+2*n,cmp1); int pre=0,cnt=0; for (int i=0; i<2*n ; i++ ) { if(point[i].x==pre) { point[i].x=cnt; } else { pre=point[i].x; point[i].x=++cnt; } } int ans=0; bulid(1,1,cnt); sort(point,point+2*n,cmp2); for (int i=0; i<2*n ; i+=2 ) { if(query(1,point[i].x,point[i+1].x)) { ans++; } } printf("%d\n",ans); } return 0; }