HDU 3255 Farming

来源:互联网 发布:梦幻群侠传3优化版攻略 编辑:程序博客网 时间:2024/05/01 22:52

感谢birdstorm提供的思路以及代码


解题思路:

线段树+扫描线+离散化

首先,先将矩形以上下线的方式记录(详见代码)

再用我们先将长方体进行切割,每次只算一层的面积(总共三层),每次只更新height值大于所扫描层数的底面矩形。

hash将x1,x2离散化,并将该线段按照上下底边分类记录进线段树内。

每次在更新线段树之前,我们先计算在此前的线段树内矩形占有的面积

以高度第一层为例

(1) 0 * y1

(2)( x2 - x1 ) * ( y3 - y1 )

(3)( x4 - x1 ) * ( y2 - y3 )

(4)( x4 - x3 ) * ( y4 - y2 )

则以上为该高度的面积并,再乘以高度差(为1)

三个高度算完之后则为正确答案。


//  author birdstorm#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <cctype>#include <cstdlib>#include <vector>#include <climits>#define MAXN 60005#define eps 1e-5#define INF 0x3f3f3f3f#define test#define For(i,m,n) for(int i=(m);i<(n);i++)#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)#define rep(i,m,n) for(int i=(m);i<=(n);i++)#define LL __int64using namespace std;struct Line{    int l, r, uod, y;    int h;} line[MAXN<<2];struct node{    int l, r, mid;    LL length, sum, cnt;} arr[MAXN<<2];LL num[MAXN];int Hash[MAXN<<1];int x[MAXN];void build(int idx, int l, int r){    arr[idx].l=l;    arr[idx].r=r;    arr[idx].length=Hash[r]-Hash[l];    arr[idx].cnt=arr[idx].sum=0;    int mid=(l+r)>>1;    arr[idx].mid=mid;    if(l<r)    {        build(idx<<1,l,mid);        build(idx<<1|1,mid,r);    }}void pushup(int idx){    if(arr[idx].cnt)        arr[idx].sum=arr[idx].length;    else    {        if(arr[idx].l+1==arr[idx].r)            arr[idx].sum=0;        else            arr[idx].sum=arr[idx<<1].sum+arr[idx<<1|1].sum;    }}void update(int idx, int l, int r, int val){    if(arr[idx].l>=l&&arr[idx].r<=r)        arr[idx].cnt+=val;    else    {        if(arr[idx].mid>l)            update(idx<<1,l,r,val);        if(arr[idx].mid<r)            update(idx<<1|1,l,r,val);    }    pushup(idx);}bool cmp(Line a, Line b){    return a.y<b.y;}int main(){    int t, cs=1;    int n, m, l, r;    int x1, x2, y1, y2, type;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        rep(i,1,m)            scanf("%I64d",&num[i]);        int tot=1;        rep(i,1,n)        {            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&type);            int down=tot, up=tot+1;         // make it a line            line[up].l=line[down].l=x1;     //left->right            line[up].r=line[down].r=x2;            line[up].h=line[down].h=num[type];            line[down].y=y1;        // high            line[up].y=y2;            line[down].uod=1;       // kind            line[up].uod=-1;            Hash[down]=x1, Hash[up]=x2;     //there are each begin and end            tot+=2;        }        sort(line+1,line+tot,cmp);        sort(Hash+1,Hash+tot);        sort(num+1,num+m+1);        int cnt=unique(Hash+1,Hash+tot)-Hash;        LL ans=0;        rep(j,1,m)        {            build(1,1,cnt-1);            LL temp=0;            int pre=0;            rep(i,1,tot-1)          //  discretization of the x                if(line[i].h>=num[j])                {                    temp+=arr[1].sum*(line[i].y-line[pre].y);                    int x1=lower_bound(Hash+1,Hash+cnt,line[i].l)-Hash;                    int x2=lower_bound(Hash+1,Hash+cnt,line[i].r)-Hash;                    update(1,x1,x2,line[i].uod);                    pre=i;                }            ans+=temp*(num[j]-num[j-1]);        }        printf("Case %d: %I64d\n",cs++,ans);    }    return 0;}






0 0