线段树 面积并 模板题

来源:互联网 发布:zabbix的端口号是多少 编辑:程序博客网 时间:2024/06/17 11:15

hdu 1542

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542

面积并不需要pushdown操作,因为不需要查询,但要pushup向上更新

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define maxn 100030#define lson step<<1#define rson step<<1|1#define getMID (l+r)>>1using namespace std;struct Tree{    int l,r,date;    double tsum;}tree[maxn*3];struct Node{    double l,r,h;    int date;//记录出边,和入边,分别为1和-1 }s[maxn];int lazy[maxn*3],cnt;//用lazy数组来记录某段区间是否要纳入长度进行计算 double pos[maxn];//离散数组 bool cmp(Node p,Node q){    return p.h<q.h;}void getlen(int root){    if (lazy[root]>0)     tree[root].tsum=pos[tree[root].r+1]-pos[tree[root].l];//如果lazy数组为正数,更新长度     else if (tree[root].l==tree[root].r)//更新到叶子节点,置零      tree[root].tsum=0;    else tree[root].tsum=tree[root<<1].tsum+tree[root<<1|1].tsum; }void build(int root,int l,int r){    tree[root].l=l;    tree[root].r=r;    tree[root].tsum=0;    if (l==r) return;    int mid=(l+r)>>1;    build(root<<1,l,mid);    build(root<<1|1,mid+1,r);}void update(int root,int left,int right,int l,int r,int val){    if (left==l && right==r)    {        lazy[root]+=val;        getlen(root);        return;    }    int mid=(left+right)>>1;    if (r<=mid) update(root<<1,left,mid,l,r,val);    else if (l>mid) update(root<<1|1,mid+1,right,l,r,val);    else    {       update(root<<1,left,mid,l,mid,val);       update(root<<1|1,mid+1,right,mid+1,r,val);    }    getlen(root);}void getline(double x1,double x2,double y1,int date) {    s[cnt].l=x1;    s[cnt].r=x2;    s[cnt].h=y1;    s[cnt].date=date;    cnt++;}int main(){    int n,num,cas=0;    while (scanf("%d",&n)!=EOF && n)    {        cnt=0;        num=0;        memset(lazy,0,sizeof(lazy));        for (int i=0;i<n;i++)        {            double x1,x2,y1,y2;            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);            getline(x1,x2,y1,1);            getline(x1,x2,y2,-1);            pos[num++]=x1;//离散化             pos[num++]=x2;        }        sort(s,s+cnt,cmp);//按高度y排好序         sort(pos,pos+num);        int tem=1;        for (int i=1;i<num;i++)//去重         {            if (pos[i]!=pos[i-1])             pos[tem++]=pos[i];        }        /*int tem;去重 int len=unique(pos,pos+num)-pos;tem=len; */        build(1,0,tem-1);        double res=0;        for (int i=0;i<cnt-1;i++)//注意是cnt-1         {            int l=lower_bound(pos,pos+tem,s[i].l)-pos;            int r=lower_bound(pos,pos+tem,s[i].r)-pos-1;//由于是以节点来维护线段长度,可让r减去1             update(1,0,tem-1,l,r,s[i].date);            res+=(s[i+1].h-s[i].h)*tree[1].tsum;//逐次计算每次扫描时的面积,累加             //注意,每次更新后就应计算面积         }        printf("Test case #%d\n",++cas);        printf("Total explored area: %.2f\n\n",res);    }}