zoukankan      html  css  js  c++  java
  • poj 2528 Mayor's posters(线段树区点)

    题目链接:  http://poj.org/problem?id=2528

    题目大意:   给出一面宽度未知的海报墙

                      再给出N张海报,每张海报会贴在墙的区间[a,b],高度与墙相等

                      所有的海报按照顺序贴完,最后可以看到多少张海报(露出来就算)

    解题思路:   海报所占用的区间可能会非常大,空间复杂度很高

                      所以首先要做的就是离散化所有海报的区间

                      如:  1  4

                                4  6

                                10  20

                                1000  2000

                      离散化:   1  2

                                      2  3

                                      4  5

                                      6  7

                       最多有2W张海报,所以总的区间最大才[1,20000]

                       时间复杂度和空间复杂度都有很大的降低

                       问题转化成线段树N次区间插入和单点查询,然后计算总区间有多少不同的数

                       如第一张海报向区间[1,2]插入数字1,第二章海报向区间[2,3]插入数字2,依次类推

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define MAX 20100
    #define MID(a,b) ((a+b)>>1)
    #define L(a) a<<1
    #define R(a) (a<<1|1)
    int a[MAX],b[MAX];
    typedef struct{
        int left,right;
        int add,num;
    }Node;
    struct snode{
    	int a,b;
    }Nodes[MAX];
    Node Tree[MAX<<2];
    int Q[10000100]={0};
    
    void Build(int t,int l,int r)
    {
    	Tree[t].left=l,Tree[t].right=r;
    	if(Tree[t].left==Tree[t].right)
    	{
    		Tree[t].add=Tree[t].num=0;
    		return ;
    	}
    	int mid=MID(Tree[t].left,Tree[t].right);
    	Build(L(t),l,mid);
    	Build(R(t),mid+1,r);
    }
    
    void Insert(int t,int l,int r,int m)
    {
    	if(Tree[t].left==l&&Tree[t].right==r)
    	{
    		Tree[t].add=m;
    		Tree[t].num=m;
    		return ;
    	}
    	int mid;
    	mid=(Tree[t].left+Tree[t].right)/2;
    	if(Tree[t].add!=0)
    	{
            Tree[L(t)].num=Tree[t].add;
    		Tree[R(t)].num=Tree[t].add;
    		Tree[L(t)].add=Tree[R(t)].add=Tree[t].add;
    		Tree[t].add=0;
    	}
    	if(l>mid)
    	{
    		Insert(R(t),l,r,m);
    	}
    	else if(r<=mid)
    	{
    		Insert(L(t),l,r,m);
    	}
    	else
    	{
    		Insert(L(t),l,mid,m);
    		Insert(R(t),mid+1,r,m);
    	}
    }
    
    int Query(int t,int l,int r)
    {
        if(Tree[t].left==l&&Tree[t].right==r)
        {
    		return Tree[t].num;
        }
        int mid=MID(Tree[t].left,Tree[t].right);
        if(Tree[t].add!=0)
        {
    		Tree[L(t)].num=Tree[t].add;
    		Tree[R(t)].num=Tree[t].add;
    		Tree[L(t)].add=Tree[R(t)].add=Tree[t].add;
    		Tree[t].add=0;    
        }
        if(l>mid)
        {
    		return Query(R(t),l,r);
        }
        else if(r<=mid)
        {
    		return Query(L(t),l,r);
        }
        else
        {
    		return Query(L(t),l,mid)+Query(R(t),mid+1,r);
        }
    }
    
    int main()
    {
        int n,m,i,j,k,t,max;
        scanf("%d",&t);
        while(t--)
        {
    		memset(Tree,0,sizeof(Tree));
    		scanf("%d",&n);
    		for(i=0,k=0;i<n;i++)
    		{
    			scanf("%d%d",&Nodes[i].a,&Nodes[i].b);
    			a[k++]=Nodes[i].a,a[k++]=Nodes[i].b;    //离散化处理
    		}
    		sort(a,a+k);        //排序
    		m=0;
    		b[m++]=a[0];
    		for(i=1;i<k;i++)
    		{
    			if(a[i]!=a[i-1])
    				b[m++]=a[i]; //记录有多少个不同的数
    		}
    		for(i=0;i<m;i++)
    		{
    			Q[b[i]]=i+1;     //每个数都对应一个编号
    		}
    		max=m;
    		Build(1,1,max);      //建立线段树[1,m]
    		for(i=0;i<n;i++)
    		{
    			Insert(1,Q[Nodes[i].a],Q[Nodes[i].b],i+1);  //插入海报
    		}
    		for(i=0;i<max;i++)
    		{
    			a[i]=Query(1,i+1,i+1);        //m次查询
    		}
    		m=1;
    		sort(a,a+max);
    		for(i=1;i<max;i++)
    		{
    			if(a[i]!=a[i-1])  //计算有多少不同发数
    				m++; 
    		}
    		printf("%d\n",m);
        }
    	return 0;
    }
    
    


    注:原创文章,转载请注明出处

                      

  • 相关阅读:
    函数二
    python控制台输出带颜色的文字方法
    is 和 == 的区别
    基本数据类型(dict)
    基本数据类型(list,tuple)
    基本数据类型(int,bool,str)
    Python运算符与编码
    Java并发编程:synchronized
    泛型中? super T和? extends T的区别
    java中的匿名内部类总结
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3138736.html
Copyright © 2011-2022 走看看