[线段树] (线段树 + 扫描线 + 离散化)

POJ 1151 && HDU 1542 Atlantis

做模板
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
typedef long long LL;
const int MAXN = 2000 + 5;
int Col[MAXN<<4],q,cnt,res,n,m,k;
double X[MAXN<<4],Sum[MAXN<<4];
struct node {
    double l,r,h;
    int d;
    node() {}
    node(double l,double r,double h,int d):l(l),r(r),h(h),d(d) {}  
    bool operator < (const node & tmp) const {
        return h < tmp.h;
    }
}tree[MAXN];


void pushup(int rt,int l,int r) {
    if (Col[rt]) Sum[rt] = X[r+1]-X[l];
    else if (l==r) Sum[rt] = 0;
    else Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
}

void update(int L, int R, int val,int x,int l, int r) {
    if(L<=l && r<= R) {
        Col[x]+=val;
        pushup(x,l,r);
        return ;
    }
    int mid=(l+r)/2;
    if(L<=mid) update(L,R,val,x<<1,l,mid);
    if(R>mid) update(L,R,val,x<<1|1,mid+1,r);
    pushup(x,l,r);
}
int main() {
    int cas = 1;
  //  freopen("1.in","r",stdin);
    while(~scanf("%d",&q)&&q) {
        n=0,m=0;
        for(int i=1;i<=q;i++) {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            tree[++m]=node(x1,x2,y1,1);
            X[++n]=x1;
            tree[++m]=node(x1,x2,y2,-1);
            X[++n]=x2;
        }
        sort(X+1,X+n+1);
        sort(tree+1,tree+m+1);
        k=1;
        for(int i=2;i<=n;i++) {
            if(X[i]!=X[i-1]) X[++k]=X[i];
        }
        memset(Sum,0,sizeof(Sum));
        memset(Col,0,sizeof(Col));
        double ans=0;
        for(int i=1;i<m;i++){
            int l=lower_bound(X,X+k,tree[i].l)-X;
            int r=lower_bound(X,X+k,tree[i].r)-X-1;//利用[ , ),这个区间性质,左闭右开
            update(l,r,tree[i].d,1,1,k-1);
            ans+=Sum[1]*(tree[i+1].h-tree[i].h);
        }
        printf("Test case #%d\nTotal explored area: %.2f\n\n",cas++ , ans);
    }
    return 0;
}
POJ的编译器果然很精妙。

事实上,对于printf(),无论是%f还是%lf,效果都是一样的。

因为,遇到float,printf()会将float类型自动提升到double,所以不会有什么问题。

而且严格地讲,printf()并没有对于%lf的定义,虽然很多编译器会接受,所以最好使用%f。

然而POJ的并不接受。QAQ

2017 ACM/ICPC 南宁区 网络赛 Overlapping Rectangles

Overlapping Rectangles
也是一道一样题目,稍微改改板子就行~

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
typedef long long LL;
const int MAXN = 2000 + 5;
int Col[MAXN<<4],q,cnt,res,n,m,k;
double X[MAXN<<4],Sum[MAXN<<4];
struct node {
    double l,r,h;
    int d;
    node() {}
    node(double l,double r,double h,int d):l(l),r(r),h(h),d(d) {}  
    bool operator < (const node & tmp) const {
        return h < tmp.h;
    }
}tree[MAXN];


void pushup(int rt,int l,int r) {
    if (Col[rt]) Sum[rt] = X[r+1]-X[l];
    else if (l==r) Sum[rt] = 0;
    else Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
}

void update(int L, int R, int val,int x,int l, int r) {
    if(L<=l && r<= R) {
        Col[x]+=val;
        pushup(x,l,r);
        return ;
    }
    int mid=(l+r)/2;
    if(L<=mid) update(L,R,val,x<<1,l,mid);
    if(R>mid) update(L,R,val,x<<1|1,mid+1,r);
    pushup(x,l,r);
} 
int main() {
    int cas = 1;
  //  freopen("1.in","r",stdin);
    while(~scanf("%d",&q)) {
        if(q==0){
            printf("*\n");
            return 0;
        }
        n=0,m=0;
        for(int i=1;i<=q;i++) {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            tree[++m]=node(x1,x2,y1,1);
            X[++n]=x1;
            tree[++m]=node(x1,x2,y2,-1);
            X[++n]=x2;
        }
        sort(X+1,X+n+1);
        sort(tree+1,tree+m+1);
        k=1;
        for(int i=2;i<=n;i++) {
            if(X[i]!=X[i-1]) X[++k]=X[i];
        }
        memset(Sum,0,sizeof(Sum));
        memset(Col,0,sizeof(Col));
        double ans=0;
        for(int i=1;i<m;i++){
            int l=lower_bound(X,X+k,tree[i].l)-X;
            int r=lower_bound(X,X+k,tree[i].r)-X-1;//利用[ , ),这个区间性质,左闭右开
            update(l,r,tree[i].d,1,1,k-1);
            ans+=Sum[1]*(tree[i+1].h-tree[i].h);
        }
        printf("%.0f\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值