zoukankan      html  css  js  c++  java
  • [poj] 1389 Area of Simple Polygons

    原题

    线段树+扫描线

    对于这样一个不规则图形,我们要求他的面积有两种方法,割和补。
    补显然不行,因为补完你需要求补上去的内部分不规则图形面积……
    那么怎么割呢?
    像这样:

    我们就转化成了无数个矩形的和。要想求这些矩形的面积,也就是底成高。因为我们并不懂什么二维线段树,所以我们就用“扫描线”(从左到右的更新计算)。
    不妨把y轴当做一个线段树,然后维护哪些位置被覆盖了,直到下一条更新,所增加的面积就是被覆盖位置(高)和这两个距离的差(底)的乘积。
    Eg:

    我们第一次更新建了第一条边的树,第二次更新时就可以增加这么多的长度。

    然后我们考虑这样一个情况,如果某个位置被覆盖了很多次怎么办,显然我们线段树的维护是不能将它重复计算多次的,那么我们就加一个cover数组,来记录当前区间被覆盖过多少次,那样在做下面这样的更新时就不会出错。

    接下来来理解代码把~!

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 1010
    #define M 60010
    using namespace std;
    int x1,y1,x2,y2,s[4*M],cov[4*M],ans,tot,mxy;
    struct hhh
    {
        int x,yf,yb,k;
        bool operator < (const hhh &b) const
    	{
    	    if (x==b.x) return k<b.k;
    	    return x<b.x;
    	}
    }a[2*N];
    
    int read()
    {
        int ans=0,fu=1;
        char j=getchar();
        for (;(j<'0' || j>'9') && j!='-';j=getchar()) ;
        if (j=='-') j=getchar();
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void modify(int i,int l,int r,int x,int y,int k)
    {
        if (x<=l && y>=r)
        {
    	cov[i]+=k;
    	if (cov[i]) s[i]=r-l+1;
    	else if (l==r) s[i]=0;
    	else s[i]=s[i*2]+s[i*2+1];
        }
        else
        {
    	int mid=(l+r)>>1;
    	if (x<=mid) modify(i*2,l,mid,x,y,k);
    	if (y>mid) modify(i*2+1,mid+1,r,x,y,k);
    	if (!cov[i]) s[i]=s[i*2]+s[i*2+1];
        }
    }
    
    int main()
    {
        while (~scanf("%d%d%d%d",&x1,&y1,&x2,&y2))
        {
    	mxy=0;
    	tot=1;
    	if (x1==-1 && y1==-1 && x2==-1 && y2==-1) break;
    	memset(cov,0,sizeof(cov));
    	memset(s,0,sizeof(s));
    	while (1)
    	{
    	    if (x1==-1 && y1==-1 && x2==-1 && y2==-1) break;
    	    mxy=max(mxy,y2);
    	    a[tot].x=x1;a[tot].yf=y1;a[tot].yb=y2;a[tot++].k=1;
    	    a[tot].x=x2;a[tot].yf=y1;a[tot].yb=y2;a[tot++].k=-1;
    	    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    	}
    	sort(a+1,a+tot);
    	ans=0;
    	modify(1,0,mxy,a[1].yf+1,a[1].yb,a[1].k);
    	for (int i=2;i<tot;i++)
    	{
    	    ans+=s[1]*(a[i].x-a[i-1].x);
    	    modify(1,0,mxy,a[i].yf+1,a[i].yb,a[i].k);
    	}
    	printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    语法上的小trick
    [算法模版]斜率优化
    CF886E Maximum Element
    【hdu 1576】A/B(数论--拓展欧几里德 求逆元 模版题)
    【poj 3090】Visible Lattice Points(数论--欧拉函数 找规律求前缀和)
    【poj 2478】Farey Sequence(数论--欧拉函数 找规律求前缀和)
    【poj 1284】Primitive Roots(数论--欧拉函数 求原根个数){费马小定理、欧拉定理}
    【poj 2407】Relatives(数论--欧拉函数 模版题)
    【bzoj 2038】 [2009国家集训队]小Z的袜子(算法效率--莫队分块算法 模版题)
    【uva 1312】Cricket Field(算法效率--技巧枚举)
  • 原文地址:https://www.cnblogs.com/mrha/p/7881151.html
Copyright © 2011-2022 走看看