扫描线

扫描线:离散x坐标,排序y坐标,从下到上扫描每一个点所在的线
面积:每次扫描就更新底面的长度 ,每次增加的面积 == 高度差 * 底面长度
周长:除了更新地面长度外,还要更新左右端点是否被覆盖,每次增加的周长就是 
	 上下两次底面长度的差值绝对值 + 未被覆盖的左右端点个数乘高度差
	更新:左闭右开 【l,r)  

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


poj 1177 题目链接

求周长

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
const int N = 5555 * 4;   ///  [-10000,10000] 区间长度为2e4
const int INF = 0x3f3f3f3f;
struct node{
    int x,y,h,f;
    bool operator < (const node &p) const{
        return h < p.h;
    }
    node() {}
    node(int a,int b,int c,int d):x(a),y(b),h(c),f(d){}
}s[N];
int tree[N << 2],lazy[N << 2],num[N << 2],lr[N << 2],rr[N << 2];
void push_up(int l,int r,int id)
{
    if (lazy[id]){
        tree[id] = r - l + 1;
        num[id] = 1;
        lr[id] = rr[id] = 1;
    }
    else if (l == r){
        tree[id] = 0;
        num[id] = 0;
        lr[id] = rr[id] = 0;
    }
    else {
        tree[id] = tree[id << 1] + tree[id << 1 | 1];
        num[id] = num[id << 1] + num[id << 1 | 1] - (lr[id << 1 | 1] & rr[id << 1]);
        lr[id] = lr[id << 1];
        rr[id] = rr[id << 1 | 1];
    }
}
void build(int l,int r,int id)
{
    tree[id] = num[id] = lazy[id] = lr[id] = rr[id] = 0;
    if (l != r){
        int mid = (l + r) >> 1;
        build(l,mid,id << 1);
        build(mid + 1,r,id << 1 | 1);
    }
}
void update(int a,int b,int flag,int l,int r,int id)
{
    if (a <= l && r <= b){
        lazy[id] += flag;
        push_up(l,r,id);
        return ;
    }
    int mid = (l + r) >> 1;
    if (a <= mid) update(a,b,flag,l,mid,id << 1);
    if (b > mid) update(a,b,flag,mid + 1,r,id << 1 | 1);
    push_up(l,r,id);
}
int main()
{
    int n;
    while(scanf("%d",&n) == 1){
        int cnt = 0;
        int mi = INF,mx = -INF;
        for (int i = 0; i < n; i++){
            int x3,x4,y3,y4;
            scanf("%d %d %d %d",&x3,&y3,&x4,&y4);
            x3 += 11000;
            x4 += 11000;
            y3 += 11000;
            y4 += 11000;
            s[cnt++] = node(x3,x4,y3,1);
            s[cnt++] = node(x3,x4,y4,-1);
            mi = min(mi,min(x3,x4));
            mx = max(mx,max(x3,x4));
        }
        build(mi,mx - 1,1);
        sort(s,s + cnt);
        int ans = 0,pre = 0;
        for (int i = 0; i < cnt; i++){
            update(s[i].x,s[i].y - 1,s[i].f,mi,mx - 1,1);
         //   cout << s[i].x << " " << s[i].y << " " << s[i].f << " " << mi << " " << mx << endl;
            ans += (s[i + 1].h - s[i].h) * (2 * num[1]);
            ans += abs(tree[1] - pre);
            pre = tree[1];
        }
        cout << ans << endl;
    }
	return 0;
}


hdu 1542 题目链接

求覆盖的面积

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
const int N = 444;
const int INF = 0x3f3f3f3f;
struct node{
    double l,r,h;
    int f;
    node(){}
    node(double a,double b,double c,int d):l(a),r(b),h(c),f(d){}
    bool operator < (const node &p) const{
        return h < p.h;
    }
}s[N];
int lazy[N << 2];
double X[N << 2],tree[N << 2];
void push_up(int id,int l,int r)
{
    if (lazy[id]){
        tree[id] = X[r + 1] - X[l];
    }
    else if (l == r) {
        tree[id] = 0;
    }
    else {
        tree[id] = tree[id << 1] + tree[id << 1 | 1];
    }
}
void update(int flag,int a,int b,int l,int r,int id)
{
    if (a <= l && r <= b){
        lazy[id] += flag;
        push_up(id,l,r);
        return ;
    }
    int mid = (l + r) >> 1;
    if (a <= mid) update(flag,a,b,l,mid,id << 1);
    if (b > mid) update(flag,a,b,mid + 1,r,id << 1 | 1);
    push_up(id,l,r);
}
int main()
{
    int n,Case = 1;
    while(scanf("%d",&n) == 1 && n){
        int cnt = 0;
        for (int i = 0; i < n; i++){
            double x3,y3,x4,y4;
            scanf("%lf %lf %lf %lf",&x3,&y3,&x4,&y4);
            s[cnt] = node(x3,x4,y3,1);
            X[cnt++] = x3;
            s[cnt] = node(x3,x4,y4,-1);
            X[cnt++] = x4;
        }
        sort(s,s + cnt);
        sort(X,X + cnt);
        int len = unique(X,X + cnt) - X;
        double ans = 0;
        for (int i = 0; i < cnt; i++){
            int a = lower_bound(X,X + len,s[i].l) - X;
            int b = lower_bound(X,X + len,s[i].r) - X - 1;
            update(s[i].f,a,b,0,len - 1,1);
           // cout << "a = " << a << " b = " << b << " " << tree2[0] << endl;
            ans += (s[i + 1].h - s[i].h) * tree[1];
        }
        printf("Test case #%d\nTotal explored area: %.2f\n",Case++,ans);
        cout << endl;
    }
	return 0;
}


hdu 1255 题目链接

hdu1542 升级版,覆盖两次的面积
离散化x坐标,更新区间为左闭右开
计算时就 X[(r + 1)] - x[l]

#include <bits/stdc++.h>
using namespace std;
const int N = 2e4 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 10007;
typedef long long ll;
struct node{
    double l,r,h;
    int flag;
    node(){}
    node(double a,double b,double c,int d):l(a),r(b),h(c),flag(d){}
    bool operator < (const node &p) const{
        return h < p.h;
    }
}s[N];
int lazy[N << 2];
double X[N << 2],tree[N << 2],tree2[N << 2];
void push_up(int id,int l,int r)
{
	/// 因为更新区间时r - 1了,所以现在要加1回去
    if (lazy[id] >= 2){
        tree2[id] = X[r + 1] - X[l];
    }
    else if (lazy[id] == 1){
        tree2[id] = tree[id << 1] + tree[id << 1 | 1];
        tree[id] = X[r + 1] - X[l];
    }
    else {
         tree2[id] = tree2[id << 1] + tree2[id << 1 | 1];
         tree[id] = tree[id << 1] + tree[id << 1 | 1];
    }
}
void update(int flag,int a,int b,int l,int r,int id)
{
    if (a <= l && r <= b){
        lazy[id] += flag;
        push_up(id,l,r);
        return ;
    }
    int mid = (l + r) >> 1;
    if (a <= mid) update(flag,a,b,l,mid,id << 1);
    if (b > mid) update(flag,a,b,mid + 1,r,id << 1 | 1);
    push_up(id,l,r);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        int cnt = 0;
        for (int i = 0; i < n; i++){
            double x3,y3,x4,y4;
            scanf("%lf %lf %lf %lf",&x3,&y3,&x4,&y4);
            s[cnt] = node(x3,x4,y3,1);
            X[cnt++] = x3;
            s[cnt] = node(x3,x4,y4,-1);
            X[cnt++] = x4;
        }
        sort(s,s + cnt);
        sort(X,X + cnt);
        int len = unique(X,X + cnt) - X;
        double ans = 0;
        for (int i = 0; i < cnt; i++){
            int a = lower_bound(X,X + len,s[i].l) - X;
            int b = lower_bound(X,X + len,s[i].r) - X - 1;
            update(s[i].flag,a,b,0,len - 1,1);
           // cout << "a = " << a << " b = " << b << " " << tree2[0] << endl;
            ans += (s[i + 1].h - s[i].h) * tree2[1];
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

hdu 3642 题目链接

三维扫描

按Z排序成每一层,然后每一层都进行一次扫描线的面积计算,得到的面积乘上高度差就是那一层的结果
初始化的时候需要扫到下一层,因为下一层会影响到更新(push_up的时候没有特判 l==r 这种情况)
当然,直接四个memset初始化也可以

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 2222;
const int INF = 0x3f3f3f3f;
typedef long long ll;
struct node{
    int l,r,h,f;
    node(){}
    node(int a,int b,int c,int d):l(a),r(b),h(c),f(d){}
    bool operator < (const node &p) const{
        return h < p.h;
    }
}s[N];
struct Point{
    int x3,x4,y3,y4,z3,z4;
    void init() {cin >> x3 >> y3 >> z3 >> x4 >> y4 >> z4;}
}p[N];
int lazy[N << 2],tree[N << 2],tree2[N << 2],tree3[N << 2];
int X[N << 2],Z[N << 2];
void push_up(int l,int r,int id)
{
    if (lazy[id] >= 3){
        tree3[id] = X[r + 1] - X[l];
    }
    else if (lazy[id] == 2){
        tree3[id] = tree[id << 1] + tree[id << 1 | 1];
        tree2[id] = X[r + 1] - X[l];
    }
    else if (lazy[id] == 1){
        tree3[id] = tree2[id << 1] + tree2[id << 1 | 1];
        tree2[id] = tree[id << 1] + tree[id << 1 | 1];
        tree[id] = X[r + 1] - X[l];
    }
    else {
        tree3[id] = tree3[id << 1] + tree3[id << 1 | 1];
        tree2[id] = tree2[id << 1] + tree2[id << 1 | 1];
        tree[id] = tree[id << 1] + tree[id << 1 | 1];
    }
}
void build(int l,int r,int id)
{
    tree[id << 1] = tree2[id << 1] = tree3[id << 1] = lazy[id << 1] = 0;
    tree[id << 1 | 1] = tree2[id << 1 | 1] = tree3[id << 1 | 1] = lazy[id << 1 | 1] = 0;
    if (l != r){
        int mid = (l + r) >> 1;
        build(l,mid,id << 1);
        build(mid + 1,r,id << 1 | 1);
    }
}
void update(int flag,int a,int b,int l,int r,int id)
{
    if (a <= l && r <= b){
    //    cout << "lazyid = " << lazy[id] << " id = " << id << endl;
        lazy[id] += flag;
        push_up(l,r,id);
        return ;
    }
    int mid = (l + r) >> 1;
    if (a <= mid) update(flag,a,b,l,mid,id << 1);
    if (b > mid) update(flag,a,b,mid + 1,r,id << 1 | 1);
    push_up(l,r,id);
}
int main()
{
    int t,Case = 1;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        int cnt = 0;
        for (int i = 0; i < n; i++){
            p[i].init();
            Z[cnt++] = p[i].z3;
            Z[cnt++] = p[i].z4;
        }
        if (n < 3){
            printf("Case %d: 0\n",Case++);
            continue;
        }
        sort(Z,Z + cnt);
        cnt = unique(Z,Z + cnt) - Z;
        ll ans = 0;
        for (int i = 0; i < cnt - 1; i++){
            int k = 0;
            for (int j = 0; j < n; j++){
                if (p[j].z3 <= Z[i] && Z[i] < p[j].z4){
                    X[k] = p[j].x3;
                    s[k++] = node(p[j].x3,p[j].x4,p[j].y3,1);
                    X[k] = p[j].x4;
                    s[k++] = node(p[j].x3,p[j].x4,p[j].y4,-1);
                }
            }
            sort(X,X + k);
            sort(s,s + k);
            int len = unique(X,X + k) - X;
            //memset(tree,0,sizeof(tree));
           // memset(tree2,0,sizeof(tree2));
           // memset(tree3,0,sizeof(tree3));
           // memset(lazy,0,sizeof(lazy));
            build(0,len - 1,1);
            ll res = 0;
            for (int j = 0; j < k - 1; j++){
                int a = lower_bound(X,X + len,s[j].l) - X;
                int b = lower_bound(X,X + len,s[j].r) - X - 1;
                update(s[j].f,a,b,0,len - 1,1);
                res += 1ll * tree3[1] * (s[j + 1].h - s[j].h);
           //     cout << "i = " << i << " a = " << a << " b = " << b << " len - 1= " << len - 1 << " res = " << res << "  tree3[1] = " << tree3[1] << endl;
            }
            ans += res * (Z[i + 1] - Z[i]);
        }
        printf("Case %d: %I64d\n",Case++,ans);
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值