zoukankan      html  css  js  c++  java
  • 线段树+扫描线【bzoj1645】[USACO07OPEN]城市的地平线City Horizon

    Description

    约翰带着奶牛去都市观光。在落日的余晖里,他们看到了一幢接一幢的摩天高楼的轮廓在地平线 上形成美丽的图案。以地平线为 X 轴,每幢高楼的轮廓是一个位于地平线上的矩形,彼此间可能有 重叠的部分。奶牛一共看到了 N 幢高楼,第 i 幢楼的高度是 Hi,两条边界轮廓在地平线上的坐标是 Ai 到 Bi。请帮助奶牛们计算一下,所有摩天高楼的轮廓覆盖的总面积是多少。

    Input

    第一行一个整数N,然后有N行,每行三个正整数ai、bi、Hi。

    Output

    一个数,数列中所有元素的和。

    刚开始被吓得以为是个二分,发现不会。然后放弃了一段时间。

    今天随机跳题跳到这个,发现这不是裸的扫描线问题咩。 。。

    我们对于摩天大楼,记录其下边界为(0),上边界即为摩天大楼的高度。

    然后最左侧坐标即为(a_i),最右侧坐标即为(b_i)

    然后对于横坐标离散化一下,我们直接跑扫描线即可。

    PS:记得开(long long)还有数组要开大!!

    代码

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define int long long 
    #define R register
    
    using namespace std;
    
    const int gz=100008;
    
    inline void in(R int &x)
    {
    	R int f=1;x=0;char s=getchar();
    	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    	x*=f;
    }
    
    struct ode
    {
    	int l,r,h,f;
    	bool operator <(const ode&a)const
    	{
    		return h<a.h;
    	}
    }edge[gz<<1];
    
    struct cod
    {
    	int l,r;
    	int len,s;
    }tr[gz<<2];
    
    int n,x[gz],tot;
    
    #define ls o<<1
    #define rs o<<1|1
    
    void build(R int o,R int l,R int r)
    {
    	tr[o].l=l,tr[o].r=r;
    	tr[o].len=tr[o].s=0;
    	if(l==r)return;
    	R int mid=(l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    }
    
    inline void up(R int o)
    {
    	if(tr[o].s)
    		tr[o].len=x[tr[o].r+1]-x[tr[o].l];
    	else if(tr[o].l==tr[o].r)
    		tr[o].len=0;
    	else tr[o].len=tr[ls].len+tr[rs].len;
    }
    
    void change(R int o,R int l,R int r ,R int k)
    {
    	if(tr[o].l==l and tr[o].r==r)
    	{
    		tr[o].s+=k;
    		up(o);
    		return;
    	}
    	R int mid=(tr[o].l+tr[o].r)>>1;
    	if(r<=mid)change(ls,l,r,k);
    	else if(l>mid)change(rs,l,r,k);
    	else change(ls,l,mid,k),change(rs,mid+1,r,k);
    	up(o);
    }
    
    signed main()
    {
    	in(n);
    	for(R int i=1,a,b,c;i<=n;i++)
    	{
    		in(a),in(b),in(c);
    		edge[++tot].l=a,edge[tot].h=0,edge[tot].r=b;
    		edge[tot].f=1;x[tot]=a;
    		edge[++tot].l=a,edge[tot].h=c;edge[tot].r=b;
    		edge[tot].f=-1;x[tot]=b;
    	}
    	sort(x+1,x+tot+1);
    	sort(edge+1,edge+tot+1);
    	R int new_n=1;
    	for(R int i=2;i<=tot;i++)
    		if(x[new_n]!=x[i])
    			x[++new_n]=x[i];
    	build(1,1,new_n);
    	R int ans=0;
    	for(R int i=1;i<=tot;i++)
    	{
    		R int l=lower_bound(x+1,x+new_n+1,edge[i].l)-x;
    		R int r=lower_bound(x+1,x+new_n+1,edge[i].r)-x-1;
    		change(1,l,r,edge[i].f);
    		ans+=(edge[i+1].h-edge[i].h)*tr[1].len;
    	}
    	printf("%lld",ans);
    }
    
  • 相关阅读:
    软件测试跟踪工具Bugzilla的安装
    Linux必备命令
    BPM Activiti5 学习资料
    23种Java设计模式-传智播客课程
    linux svn 启动 关闭
    JQuery调用iframe子页面函数/对象的方法
    判断 iframe 是否加载完成的完美方法
    java获得数据库信息常用API(DatabaseMetaData)示例
    JS动态修改页面EasyUI datebox不生效、EasyUI动态添加Class、EasyUI动态渲染解析解决方案
    旧金山大学的算法可视化学习教程 赞的教程,将抽象的算法可视化,易于理解
  • 原文地址:https://www.cnblogs.com/-guz/p/9930854.html
Copyright © 2011-2022 走看看