HDU 1828 Picture

题目链接:HDU-1828

题意为给定一堆矩形,求总周长。

HDU-1542非常类似,同样是扫描线法。

做法是每次扫到一条线后,答案加上“覆盖总长度”变化的绝对值。即:

ans+=abs(last-sum[1]);

然后横着竖着各来一次即可。

 

代码如下:

#include<cstdio>
#include<set>
#include<map>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

const int MAXN=20010;
struct Line
{
    int x1,x2,d;
    int y;
    bool operator < (Line x)
    {
        return y<x.y;
    }
    void operator = (Line x)
    {
        x1=x.x1;
        x2=x.x2;
        y=x.y;
        d=x.d;
    }
};
int dict[MAXN];
map<int,int> index;
int xx1[MAXN],xx2[MAXN],yy1[MAXN],yy2[MAXN];
set<int> S;
Line lines[MAXN];

LL mark[MAXN<<2];
int sum[MAXN<<2];
void modify(LL o,LL l,LL r,LL ml,LL mr,LL num)
{
    if(ml<=l && r<=mr)
    {
        mark[o]+=num;
        if(mark[o]) sum[o]=(dict[r+1]-dict[l]);
        else if(l==r) sum[o]=0;
        else sum[o]=sum[o*2]+sum[o*2+1];
    }
    else
    {
        LL m=(r-l)/2+l;
        if(ml<=m) modify(o*2,l,m,ml,mr,num);
        if(mr>m) modify(o*2+1,m+1,r,ml,mr,num);
        if(mark[o]) sum[o]=(dict[r+1]-dict[l]);
        else if(l==r) sum[o]=0;
        else sum[o]=sum[o*2]+sum[o*2+1];
    }
}
int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int dictnum=0;
        index.clear();
        S.clear();
        memset(sum,0,sizeof(sum));
        memset(mark,0,sizeof(mark));
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&xx1[i],&yy1[i],&xx2[i],&yy2[i]);
            S.insert(xx1[i]);
            S.insert(xx2[i]);
        }
        for(set<int>::iterator it=S.begin();it!=S.end();it++)
        {
            dict[++dictnum]=*it;
            index[*it]=dictnum;
        }
        for(int i=1;i<=n;i++)
        {
            Line tmp;
            tmp.x1=index[xx1[i]]; tmp.x2=index[xx2[i]];
            tmp.y=yy1[i]; tmp.d=1;
            lines[2*i-1]=tmp;
            tmp.y=yy2[i]; tmp.d=-1;
            lines[2*i]=tmp;
        }
        sort(lines+1,lines+1+2*n);
        int last=0;
        for(int now=1;now<=n*2;now++)
        {
            Line ing=lines[now];
            modify(1,1,dictnum-1,ing.x1,ing.x2-1,ing.d);
            ans+=abs(last-sum[1]);
            last=sum[1];
        }
        dictnum=0;
        index.clear();
        S.clear();
        memset(sum,0,sizeof(sum));
        memset(mark,0,sizeof(mark));
        for(int i=1;i<=n;i++)
        {
            S.insert(yy1[i]);
            S.insert(yy2[i]);
        }
        for(set<int>::iterator it=S.begin();it!=S.end();it++)
        {
            dict[++dictnum]=*it;
            index[*it]=dictnum;
        }
        for(int i=1;i<=n;i++)
        {
            Line tmp;
            tmp.x1=index[yy1[i]]; tmp.x2=index[yy2[i]];
            tmp.y=xx1[i]; tmp.d=1;
            lines[2*i-1]=tmp;
            tmp.y=xx2[i]; tmp.d=-1;
            lines[2*i]=tmp;
        }
        sort(lines+1,lines+1+2*n);
        last=0;
        for(int now=1;now<=n*2;now++)
        {
            Line ing=lines[now];
            modify(1,1,dictnum-1,ing.x1,ing.x2-1,ing.d);
            ans+=abs(last-sum[1]);
            last=sum[1];
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2017-02-08 15:09  HuaZhang  阅读(301)  评论(0编辑  收藏  举报