poj2528

题意:有一长度为10000000的墙,上面按时间顺序张贴长度不同,宽度相同,位置不一定相同的广告,问最终还能有多少广告能露出来。

分析:线段树。每贴一张海报就是把一个连续的区间的值全部更改,但这里的数据比较大,直接做可能时间空间复杂度都很高。因为最多只有10000张海报,而即使每张海报的两个端点都不相同,最多就有20000个有用的端点,所以可以采用映射把这些位置离散化,把这些点由小到大映射到另一个数组里,然后的线段树的操作就可以只在这个数组里进行了。

#include<cstdio>
#include<algorithm>
using std::sort;
struct line
{
    int from,pos;
    bool operator < (line b) const
    {
        return pos<b.pos;
    }
};
struct node
{
    int lchild,rchild;
    int lend,rend;
    int color;
};

int coordinate[100001][2],m,t,last;
line l[200001];
node tree[200001];
bool tag[200001];//标记有无lazy
void make_map(int i,int& m)
{
    if(l[i].pos!=l[last].pos)
    {
        last=i;
        m++;
    }
    if(l[i].from<0)
        coordinate[-l[i].from-1][1]=m;
    else
        coordinate[l[i].from-1][0]=m;
}

void lazy(int pos,int x)
{
    tag[pos]=true;
    tree[pos].color=x;
}

//前提tag[pos]==true
void unlazy(int pos)
{
    if(tree[pos].rchild!=tree[pos].lchild)//不是叶子
    {
        lazy(tree[pos].lchild,tree[pos].color);
        lazy(tree[pos].rchild,tree[pos].color);
    }
    tag[pos]=false;
}

int initTree(int a,int b)
{
    int num=++t;
    tag[num]=false;
    tree[num].color=-1;
    tree[num].lend=a;
    tree[num].rend=b;
    if(a==b)
    {
        tree[num].lchild=-1;
        tree[num].rchild=-1;
        return num;
    }
    int mid=(a+b)/2;
    tree[num].lchild=initTree(a,mid);
    tree[num].rchild=initTree(mid+1,b);
    return num;
}

void insert(int pos,int left,int right,int x)
{
    if(pos<0)
        return;
    if(left<=tree[pos].lend && right>=tree[pos].rend)//此次目标操作区间完全覆盖此区间
        lazy(pos,x);
    else
    {
        if(!(tree[pos].lend>right || tree[pos].rend<left))//有交集(不一定包含目标操作区间)
        {
            if(tag[pos])//有标记
                unlazy(pos);
            tree[pos].color=-1;
            insert(tree[pos].lchild,left,right,x);
            insert(tree[pos].rchild,left,right,x);
        }
    }
}

void dfs(int a,int& counter)
{
    if(tree[a].color==-1 && tree[a].lchild!=tree[a].rchild)
    {
        dfs(tree[a].lchild,counter);
        dfs(tree[a].rchild,counter);
    }
    else if(!tag[tree[a].color])
    {
        tag[tree[a].color]=true;
        counter++;
    }
}
int main()
{
    int c;
    scanf("%d",&c);
    while(c--)
    {
        int n;
        scanf("%d",&n);

        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&coordinate[i][0],&coordinate[i][1]);
            l[2*i].pos=coordinate[i][0];
            l[2*i].from=i+1;
            l[2*i+1].pos=coordinate[i][1];
            l[2*i+1].from=-i-1;
        }

        //make a map
        sort(l,l+2*n);
        m=1;
        last=0;
        for(int i=0;i<2*n;i++)
            make_map(i,m);

        /*printf("m=%d\n",m);
        for(int i=0;i<n;i++)
        {
            printf("coordinate[%d][0]=%d,coordinate[%d][1]=%d\n",i,coordinate[i][0],i,coordinate[i][1]);
        }*/
        //initial tree
        t=-1;
        initTree(1,m);
        t++;

        //insert the intervals
        for(int i=0;i<n;i++)
            insert(0,coordinate[i][0],coordinate[i][1],i);

        //count the posters
        int counter=0;
        for(int i=0;i<n;i++)
            tag[i]=false;
        //preorder traverse
        dfs(0,counter);
        printf("%d\n",counter);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ZShogg/p/3053941.html