• hiho_1079_离散化


    题目

        在长度为L的宣传栏上张贴N张海报,将宣传栏分为L个长度为1的单位,海报长度为整数,且高度和宣传栏相同,左右边界和宣传栏单位之间缝隙重合(即海报总是跨越整数个单位)。后贴的海报可能会覆盖之前贴的海报的全部或者部分,问N张海报贴完之后,没有被完全覆盖的海报的总数。N <= 10^6, L <= 10^9.

    分析

        区间覆盖问题,会想到用线段树来解决,直观的将L个单位视为线段树的叶子节点,但是这样做空间复杂度太高(同样时间复杂度也很高),可以将区间进行离散化: 
        将所有海报的边界先收集起来,按照从小到大排序后去重,这样得到的离散点映射到从0开始,每次增加1的一个区间上,然后将该区间映射到线段树上。 
        线段树的节点结构中维护两个信息:(1)该节点代表的区间是否只有一个海报single_post,(2)如果只有一个海报,则记录海报序号post。 
        插入海报的时候,找到海报的左右边界点对应到线段树的叶节点编号构成的区间A,然后从根节点开始递归,如果到达某个节点,该节点代表区间B和A相同,则设置该节点的single_post为true,且post为海报号,否则向下找; 
        最后查询的时候,从线段树根节点开始向下找,找到所有的区间内只有一个海报的节点,并将海报号记录下来。

    实现

    #include<iostream>
    #include<string.h>
    #include<iostream>
    #include<queue>
    #include<cmath>
    #include<unordered_map>
    #include<unordered_set>
    #include<string>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int inf = 1 << 29;
    const int kMax = 200005;
    unordered_map<int, int> discrete_map; //海报所贴的端点到线段树区间端点的映射
    int gPost[kMax >> 1][2]; //海报的左右边界
    vector<int> gPoints;	//存放海报的端点
    unordered_set<int> uncovered_post; //没有被遮盖的海报序号
    struct Node{
    	int beg;
    	int end;
    	int post;
    	bool single_post;
    	Node(){
    		beg = end = 0;
    		single_post = true;
    		post = -1;
    	}
    };
    Node gNodes[kMax << 2];
    
    //连续型的区间 线段树
    void BuildTree(int node, int beg, int end){
    	gNodes[node].beg = beg;
    	gNodes[node].end = end;
    	if (beg + 1 == end){
    		//连续型的区间,线段树的叶子节点表示一个单位长度[i, i+1],而不是一个点[i, i].				
    		return;
    	}
    	int mid = (beg + end) >> 1;
    	int left = 2 * node + 1, right = 2 * node + 2;
    	BuildTree(left, beg, mid);
    	BuildTree(right, mid, end); 
    	//连续型的区间,[beg, mid] & [mid, end]; 而离散型的区间[beg, mid]&[mid + 1, end]	
    }
    
    void PushDown(int node){
    	if (gNodes[node].beg + 1 == gNodes[node].end)
    		return;
    	if (gNodes[node].single_post){
    		int left = 2 * node + 1, right = 2 * node + 2;
    		gNodes[left].post = gNodes[right].post = gNodes[node].post;
    		gNodes[left].single_post = gNodes[right].single_post = true;
    		gNodes[node].single_post = false;
    	}
    }
    
    void Post(int node, int beg, int end, int post){
    	if (gNodes[node].beg == beg && gNodes[node].end == end){
    		gNodes[node].single_post = true;
    		gNodes[node].post = post;
    		return;
    	}
    	PushDown(node);
    	int left = 2 * node + 1, right = 2 * node + 2;
    	int mid = (gNodes[node].beg + gNodes[node].end) / 2;
    	if (beg >= mid){
    		Post(right, beg, end, post);
    	}
    	else if (end <= mid){
    		Post(left, beg, end, post);
    	}
    	else{
    		Post(left, beg, mid, post);
    		Post(right, mid, end, post);
    	}
    }
    void Query(int node){
    	if (gNodes[node].single_post && gNodes[node].post != -1){
    		uncovered_post.insert(gNodes[node].post);
    		return;
    	}
    	if (gNodes[node].beg + 1 == gNodes[node].end){
    		return;
    	}
    	int left = 2 * node + 1, right = 2 * node + 2;
    	Query(left);
    	Query(right);
    }
    
    int main(){
    	int N, L;
    	scanf("%d %d", &N, &L);
    	for (int i = 0; i < N; i++){
    		scanf("%d %d", &gPost[i][0], &gPost[i][1]);
    		//将各个离散点加入vector
    		gPoints.push_back(gPost[i][0]);
    		gPoints.push_back(gPost[i][1]);
    	}
    	
    	//先排序
    	sort(gPoints.begin(), gPoints.end());
    
    	//对vector去重
    	gPoints.resize(std::distance(gPoints.begin(), unique(gPoints.begin(), gPoints.end())));
    		
    	BuildTree(0, 0, gPoints.size() - 1);
    	//将离散化的点,按照大小映射到一个连续的区间,缩小数据规模
    	for (int i = 0; i < gPoints.size(); i++){
    		discrete_map[gPoints[i]] = i;
    	}
    	for (int i = 0; i < N; i++){
    		Post(0, discrete_map[gPost[i][0]], discrete_map[gPost[i][1]], i);
    	}
    	Query(0);
    	int result = uncovered_post.size();
    	printf("%d
    ", result);
    	return 0;
    }
    
  • 相关阅读:
    Knockoutjs 实践入门 (2) 绑定事件
    HTTP If-Modified-Since引发的浏览器缓存汇总
    net.sf.json和 com.fasterxml.jackson中对象转json的区别
    JPA EntityManager详解
    Spring JPA中OneToOne和OneToMany用法
    Spring Data JPA中CrudRepository与JpaRepository的不同
    Git提交撤销
    Tomcat启动报StackOverflowError
    Git分支合并冲突解决(续)
    Git分支合并冲突解决
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/5547594.html
Copyright © 2020-2023  润新知