zoukankan      html  css  js  c++  java
  • pku2528(线段树加离散化)

    悲剧呀,这道题目搞了那么久,原来是离散化的方法出现问题了,悲剧,实在悲剧

    线段树 +  离散化
       今天做了这道题目的时候,  也算是明白了 离散化 的基本
       意思,因为 题目的 数据范围很大 , 1- 10000000,直接线段树的话, 先不说
       内存会不会爆, 这么大的范围估计也是 TLE了. 
       仔细读题, 可以看到  1<= N <= 10000, 也就是说 最多只有 10000个点, 如果
       每个点都不同, 那么最多也只有 20000 个数据, 那么离散后的 范围就相当小;
       
       离散化 的大概思路 :   比如说给你一组 数据 1 4 1000 100000,  如果直接
                             开线段, 显然是浪费, 那么我们只要 进行 映射 :
                                    1    1  
                                    4    2
                                 1000    3
                               100000    4
                             接下来 我们只要对 1 2 3 4 建立线段树就行了 只需要
                             [1,4]的区间  

    嘿嘿,这个是刚写的代码,简洁了许多,也快了一点

    #include<iostream>
    #include<map>
    #include<set>
    #define MAXN 10010
    using namespace std;
    struct node
    {
    	int c;
    }p[MAXN*8];
    int left1[MAXN],right1[MAXN],n,m,num;
    bool col[MAXN];
    map<int,int> map1;
    map<int,int>::iterator it;
    void bulid(int k,int s,int t)
    {
    	if(t==s) return ;
    	p[k].c=0;
    	int kl=k<<1,kr=kl+1,mid=(s+t)>>1;
    	bulid(kl,s,mid);
    	bulid(kr,mid+1,t);
    }
    void insert(int k,int s,int t,int l,int r,int e)
    {
    	if(l>t||r<s) return ;
    	if(l<=s&&t<=r)
    	{
    		p[k].c=e;
    		return ;
    	}
    	int kl=k<<1,kr=kl+1,mid=(s+t)>>1;
    	if(p[k].c!=-1)
    	{
    		p[kl].c=p[kr].c=p[k].c;
    		p[k].c=-1;
    	}
    	insert(kl,s,mid,l,r,e);
    	insert(kr,mid+1,t,l,r,e);
    }
    void query(int k,int s,int t)
    {
    	if(p[k].c!=-1)
    	{
    		if(!col[p[k].c]) 
    		{
    			num++;
    			col[p[k].c]=true;
    		}
    		return ;
    	}
    	int kl=k<<1,kr=kl+1,mid=(s+t)>>1;
    	query(kl,s,mid);
    	query(kr,mid+1,t);
    }
    
    int main()
    {
    	int cas;
    	scanf("%d",&cas);
    	while(cas--)
    	{
    		map1.clear();
    		scanf("%d",&m);
    		for(int i=0;i<m;i++)
    		{
    			scanf("%d %d",&left1[i],&right1[i]);
    			map1[left1[i]]=10;
    			map1[right1[i]]=10;
    		}
    		it=map1.begin();
    		int i=1;
    		for(;it!=map1.end();i++,it++)
    			it->second=i;
    		n =i;
    		bulid(1,1,n);
    		for(int i=0;i<m;i++)
    			insert(1,1,n,map1[left1[i]],map1[right1[i]],i+1);
    		num=0;
    		memset(col,false,sizeof(col));
    		col[0]=true;
    		query(1,1,n);
    		printf("%d\n",num);
    	}
    	return 0;
    }
    

       

    #include<set>
    #include<map>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    using namespace std;
    #define MAX_N  20010
    struct In
    {      
           int left;
           int right;
    }str[MAX_N];
    struct Node
    {
           int l;
           int r;
           int col;       
    }p[8*MAX_N];
    set<int> my_set;
    map<int,int> mp;
    map<int,int>::iterator beg,end1;
    int cmp( const void *a , const void *b ){
        return *(int *)a-*(int *)b;
    }
    void bulid(int k,int s,int t)
    {
    	int kr,kl,mid;
    	p[k].l=s;p[k].r=t;p[k].col=0;
    	if(s==t)
    		return ;
    	mid=(s+t)>>1;kl=k<<1;kr=kl+1;
    	bulid(kl,s,mid);
    	bulid(kr,mid+1,t);
    }
    void insert(int k,int s,int t,int v)
    {
    	int kr,kl,mid;
    	if(s==p[k].l&&t==p[k].r)
    	{
    		p[k].col=v;
    	}
    	else {
    		mid=(p[k].l+p[k].r)>>1;kl=k<<1;kr=kl+1;
    		if(p[k].col!=-1)
    		{
    			p[kl].col=p[kr].col=p[k].col;
    			p[k].col=-1;
    		}
    		if(t<=mid) insert(kl,s,t,v);
    		else if(s>mid) insert(kr,s,t,v);
    		else {
    			  insert(kl,s,mid,v);
    			  insert(kr,mid+1,t,v);
    		}
    	}
    }
    void query(int k,int s,int t)
    {
    	if(p[k].col!=-1)
    	 {
    		 my_set.insert(p[k].col);//将颜色插入set中,自动去重
    	     return ;
    	}
    	int mid=(p[k].r+p[k].l)>>1,kl=k<<1,kr=kl+1;
    	if(t<=mid) query(kl,s,t) ;
    	else if(s>mid) query(kr,s,t);
    	else {
    		query(kl,s,mid);query(kr,mid+1,t);
    	}
    }
    int main()
    {
    	int i,j,cas,n,m,num;
    	scanf("%d",&cas);	
    	bulid(1,1,MAX_N);
    	while(cas--)
    	{
    		my_set.clear();
    		mp.clear();
    		scanf("%d",&n);
    		for(i=1;i<=n;i++)
    		{
    			scanf("%d %d",&str[i].left,&str[i].right);
    			 mp[str[i].left] = 10; mp[str[i].right] = 10; 
    		}
    		 beg = mp.begin(), end1 = mp.end();
    		insert(1,1,2*n,0);
          //因为map 已经自动排序了,所以直接从 1 --> N 开始标记, 离散化 
               for ( int i = 1;beg != end1; ++ beg, ++ i ) {         
                    beg->second = i;  
               }
               //因为线段树已经建立好了, 所以没必要每次都重建一次, 只要插入一条
               //覆盖所有区间的 底板 就行了 
               for ( int i = 1; i <= n; ++ i ) {
                    //用离散后的标记 插入 线段 
                    insert ( 1,mp[str[i].left], mp[str[i].right], i );   
               }
    		query(1,1,2*n);
    		num=my_set.size();//返回集合中元素个数
    		if(*my_set.begin()==0)
    		   num--;
    		printf("%d\n",num);
    	}
    	return 0;
    }
    
  • 相关阅读:
    时间随手记
    laravel简书(2)
    laravel简书(1)
    <<Design Patterns>> Gang of Four
    计算机网络你还懵逼吗?持续更新!!!
    poj3126 搜索
    POJ 1426 搜索进阶
    CodeForces 660D
    poj3279搜索详解
    bfs简单题-poj2251
  • 原文地址:https://www.cnblogs.com/nanke/p/2033844.html
Copyright © 2011-2022 走看看