您的位置:首页 > 其它

poj-2528(线段树+离散化)

2015-03-25 19:42 337 查看
/*线段树+离散化
题意:在长度1~10000000的墙上贴海报,可以覆盖前一张,按输入顺序在墙上贴海报,求最后能看到几张海报。
思路:更新线段树,在左右值相同的线段区间更新为贴满,f值记录被哪张海报贴满。
      寻找区间的过程,若某父区间早被贴满,则先更新他的子区间,然后该父区间f记为0,表示不被一张海报贴满。
      区间很大,先对区间进行离散化处理。
*/
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 10000000
#define maxn 20005
int f[maxn];
int s[maxn];
bool visit[maxn];
int fn;
//int ff[maxn];
int post[maxn][2];
struct node
{
    int f;
    int l,r;
    int lv,rv;
}tree[N*5];
void build(int l,int r,int root)//建区间树
{
    tree[root].l=l;
    tree[root].r=r;
    tree[root].lv=f[l];
    tree[root].rv=f[r];
    tree[root].f=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,root*2);
    build(mid+1,r,root*2+1);
}
void update(int lv,int rv,int n,int root)//更新线段树,即新张贴一张海报
{
    if(lv>rv) return ;
    if(tree[root].lv==lv&&tree[root].rv==rv){//表示被第n张海报贴满
        tree[root].f=n;
        return;
    }
    int mid=(tree[root].l+tree[root].r)>>1;
    int midv=f[mid];
    if(tree[root].f){//当前区间不是要贴海报的区间,若之前该区间被第n张贴满,则要先更新其子区间
        int k=tree[root].f;
         update(tree[root].lv,f[mid],k,root*2);
         update(f[mid+1],tree[root].rv,k,root*2+1);
         tree[root].f=0;
    }
    if(midv>=rv) update(lv,rv,n,root*2);
    else if(midv<lv) update(lv,rv,n,root*2+1);
    else {
        update(lv,midv,n,root*2);
        update(f[mid+1],rv,n,root*2+1);
    }
}
int query(int root)//统计被贴满的区间,且不重复计数
{
    if(tree[root].f){
        if(!visit[tree[root].f]){
            visit[tree[root].f]=true;
            return 1;
        }
        return 0;
    }
    if(tree[root].l==tree[root].r) return 0;
    return query(root*2)+query(root*2+1);
}
int main()
{
    int n,t;
    int x,y;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d %d",&post[i][0],&post[i][1]);
            s[i*2]=post[i][0];
            s[i*2+1]=post[i][1];
        }
        sort(s,s+n*2);
        fn=0;
        f[++fn]=s[0];
       // ff[s[0]]=fn;
        for(int i=1;i<2*n;i++)
            if(s[i]==s[i-1]) continue;
            else {
                    f[++fn]=s[i];//离散化区间
                   // ff[s[i]]=fn;
            }
        build(1,fn,1);
        for(int i=0;i<n;i++)
            update(post[i][0],post[i][1],i+1,1);//张贴下一张海报
        memset(visit,false,sizeof(visit));
        printf("%d\n",query(1));
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: