1. 程式人生 > >線段樹+離散化poj2528

線段樹+離散化poj2528

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(int
rt) { 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; }