zoukankan      html  css  js  c++  java
  • 线段树+扫描线

    扫描线

    扫描线问题主要利用了线段树。

    因为矩形的并集比较难算,所以我们可以用(sum)(扫描线被截长度×所扫描的高度)来求和。而这样做发现可以用线段树来优化,具体优化方式如下:所扫描的高度比较好求,主要是扫描线被截长度需要优化。

    我们可以设横边有一个a权值,如果该边是矩阵的下边则设为1,相反就设为-1,这样如果一段区间(如果该区间正好与横边对应的话至少会对应两个边)的没有被截(或者说已经扫过去,加入答案中去了)则此时该区间所对应的线段树的a权值和一定为0.

    相反,如果该区间已经被扫描线扫进去且会更新答案的话,则a权值一定不为0。

    然后枚举每一条边,在线段树中更新a值和被覆盖长度的值。

    最后答案加上总区间被覆盖长度的值的和乘高度差。

    #include <bits/stdc++.h>
    #define int long long
    #define ls l, mid, root << 1
    #define rs mid + 1, r, root << 1 | 1
    using namespace std;	
    int n, cnt, _x1, _x2, _y9, _y3, x[1001000], sum;
    struct g {				
     	int l, r, y, s;		
     	bool operator < (g c) {
     		return y < c.y;	
     	}					
    }data[1001000];			
    struct node {			
     	int l, r, a, len;	
    }ans[4001000];			
    void build(int l, int r, int root) {
     	ans[root].l = l, ans[root].r = r;
     	ans[root].len = ans[root].a = 0;
     	if (l == r) return; 
     	int mid = (l + r) >> 1;
     	build(ls);
     	build(rs);
     	return;
    }
    inline void pushup(int root)
    {
    	if (ans[root].a)//如果当前已经被覆盖 
     		ans[root].len = x[ans[root].r + 1] - x[ans[root].l];//那就完全被覆盖了,就直接加上就好。 
     	else//没有被覆盖的就需要递归求解
    		ans[root].len = ans[root << 1].len + ans[root << 1 | 1].len;
    }
    void update(int ql, int qr, int root, int add)
    {
    	int l = ans[root].l, r = ans[root].r;
    	if (x[l] >= qr || x[r + 1] <= ql) return;
    	if (ql <= x[l] && x[r + 1] <= qr)	
    	{									
    		ans[root].a += add;
    		pushup(root);//完成操作后记得要更新,查看是否被覆盖了 
    		return;
    	}
     	update(ql, qr, root << 1, add);
     	update(ql, qr, root << 1 | 1, add);
    	pushup(root);
    }
    signed main()
    {
     	scanf("%lld", &n);//初始化 
     	for (int i = 1; i <= n; i++)
     	{
     	 	scanf("%lld%lld%lld%lld", &_x1, &_y9, &_x2, &_y3);
     	 	data[++cnt].l = _x1, data[cnt].r = _x2, data[cnt].s = 1, data[cnt].y = _y9; 
     	 	x[cnt] = _x1;
     	 	data[++cnt].l = _x1, data[cnt].r = _x2, data[cnt].s = -1, data[cnt].y = _y3;
     	 	x[cnt] = _x2;				
     	} //离散化					   
     	sort(data + 1, data + 1 + cnt);//离散化首先需要排序+去重
     	sort(x + 1, x + 1 + cnt);	   
     	int block = unique(x + 1, x + 1 + cnt) - (x + 1);
     	build(1, block - 1, 1); //block-1就可以包含所有的区间了。建树时的都是离散化之后的点 
     	for (int i = 1; i < cnt; i++)
    	{
     	  	update(data[i].l, data[i].r, 1, data[i].s);//更新扫描线信息
     	  	sum += ans[1].len * (data[i + 1].y - data[i].y);//面积=底X高 ,更新面积, 
    	}   
    	printf("%lld", sum);
    	return 0;
    }       
    
  • 相关阅读:
    CentOS7 防火墙firewalld详细操作
    bootstrap-datetimepicker 滚动错位问题
    Contos更换python版本
    centos7.3下使用yum 安装pip
    备注
    jenkins与SVN 问题记录
    kafka配置
    Jenkins 与github配置
    nginx File not found 错误
    nginx 总结
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11353119.html
Copyright © 2011-2022 走看看