zoukankan      html  css  js  c++  java
  • HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***

    题目链接

    题意

    给出n个矩形,求面积并。

    思路

    使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去。离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积。这里要注意线段树上结点维护的是线段的信息,而不是点的信息。
    参考资料

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int INF = 0x3f3f3f3f;
    const int N = 1e5 + 10;
    #define lson l, m, rt<<1
    #define rson m + 1, r, rt<<1|1
    struct Node {
    	int st;
    	double l, r, id;
    	bool operator < (const Node &rhs) const {
    		return id < rhs.id;
    	}
    } p[N];
    double y[N], tree[N<<2];
    int cnt[N<<2];
    
    void PushUp(int l, int r, int rt) {
    	if(cnt[rt] > 0) tree[rt] = y[r+1] - y[l]; // r + 1是因为线段树上结点是线段,映射成点就要+1
    	else if(l == r) tree[rt] = 0; // 当这个线段没有cnt的时候就代表消失了
    	else tree[rt] = tree[rt<<1] + tree[rt<<1|1];
    }
    
    void Update(int L, int R, int w, int l, int r, int rt) {
    	if(L <= l && r <= R) {
    		cnt[rt] += w;
    		PushUp(l, r, rt);
    		return ;
    	}
    	int m = (l + r) >> 1;
    	if(L <= m) Update(L, R, w, lson);
    	if(m < R) Update(L, R, w, rson);
    	PushUp(l, r, rt);
    }
    
    int main() {
    	int cas = 1, n;
    	while(scanf("%d", &n), n) {
    		int cnt = 0, m = 0;
    		for(int i = 1; i <= n; i++) {
    			double x1, x2, y1, y2;
    			scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
    			y[++cnt] = y1, y[++cnt] = y2;
    			p[++m] = (Node) { 1, y1, y2, x1 };
    			p[++m] = (Node) { -1, y1, y2, x2 };
    		}
    		sort(y + 1, y + 1 + cnt);
    		sort(p + 1, p + 1 + m);
    		cnt = unique(y + 1, y + 1 + cnt) - y - 1;
    		double ans = 0;
    		for(int i = 1; i <= m; i++) {
    			ans += tree[1] * (p[i].id - p[i-1].id);
    			int L = lower_bound(y + 1, y + 1 + cnt, p[i].l) - y;
    			int R = lower_bound(y + 1, y + 1 + cnt, p[i].r) - y - 1;
    					// R - 1是因为线段树上的结点是线段
    			Update(L, R, p[i].st, 1, cnt, 1);
    			printf("%d : %d - %d , %.2f
    ", i, L, R, tree[1]);
    		}
    		printf("Test case #%d
    ", cas++);
    		printf("Total explored area: %.2f
    
    ", ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Java实现代理服务器
    UML快速理解
    Linux常用命令
    线程数设置和CPU数的关系
    面试官:你在平时的工作中遇到过哪些问题让你印象深刻?
    常见的思考问题方法、处理问题工具
    分布式锁的几种使用方式(redis、zookeeper、数据库)
    MySQL数据库连不上?
    Oracle备份的几种方式
    ORACLE物理standby与逻辑standby简述
  • 原文地址:https://www.cnblogs.com/fightfordream/p/7591674.html
Copyright © 2011-2022 走看看