• POJ 1436 Horizontally Visible Segments(线段树)


    POJ 1436 Horizontally Visible Segments

    题目链接

    线段树处理染色问题,把线段排序。从左往右扫描处理出每一个线段能看到的右边的线段,然后利用bitset维护枚举两个线段。找出还有一个两个都有的线段

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <bitset>
    #include <vector>
    using namespace std;
    
    const int N = 8005;
    bitset<N> g[N];
    int t, n;
    
    struct Seg {
    	int x, y1, y2;
    	void read() {
    		scanf("%d%d%d", &y1, &y2, &x);
    	}
    } s[N];
    
    bool cmp(Seg a, Seg b) {
    	return a.x < b.x;
    }
    
    #define lson(x) ((x<<1)+1)
    #define rson(x) ((x<<1)+2)
    
    struct Node {
    	int l, r, val, setv;
    } node[N * 4 * 2];
    
    void pushup(int x) {
    	if (node[lson(x)].val == node[rson(x)].val) node[x].val = node[lson(x)].val;
    	else node[x].val = -1;
    }
    
    void pushdown(int x) {
    	if (node[x].setv != -1) {
    		node[lson(x)].val = node[rson(x)].val = node[x].setv;
    		node[lson(x)].setv = node[rson(x)].setv = node[x].setv;
    		node[x].setv = -1;
    	}
    }
    
    void build(int l, int r, int x = 0) {
    	node[x].l = l; node[x].r = r; node[x].val = -1; node[x].setv = -1;
    	if (l == r)
    		return;
    	int mid = (l + r) / 2;
    	build(l, mid, lson(x));
    	build(mid + 1, r, rson(x));
    }
    
    vector<int> g2[N];
    
    void add(int l, int r, int v, int x = 0) {
    	if (node[x].val != -1 && node[x].l >= l && node[x].r <= r) {
    		if (g[node[x].val][v] == false)
    			g2[node[x].val].push_back(v);
    		g[node[x].val][v] = true;
    		node[x].setv = v;
    		node[x].val = v;
    		return;
    	}
    	if (node[x].l == node[x].r) {
    		node[x].val = v;
    		return;
    	}
    	pushdown(x);
    	int mid = (node[x].l + node[x].r) / 2;
    	if (l <= mid) add(l, r, v, lson(x));
    	if (r > mid) add(l, r, v, rson(x));
    	pushup(x);
    }
    
    int main() {
    	scanf("%d", &t);
    	while (t--) {
    		scanf("%d", &n);
    		for (int i = 0; i < n; i++) {
    			g[i].reset();
    			g2[i].clear();
    			s[i].read();
    		}
    		sort(s, s + n, cmp);
    		build(0, N * 2 - 1);
    		for (int i = 0; i < n; i++)
    			add(s[i].y1 * 2, s[i].y2 * 2, i);
    		int ans = 0;
    		for (int i = 0; i < n; i++) {
    			for (int j = 0; j < g2[i].size(); j++) {
    				if (g[i][g2[i][j]])
    					ans += (g[i]&g[g2[i][j]]).count();
    			}
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }


  • 相关阅读:
    手工解析.NET完全限定类型名称
    用Lambda表达式进行函数式编程(续):用C#实现Y组合子
    VS2008亮点:用Lambda表达式进行函数式编程
    用GPU通用并行计算绘制曼德勃罗特集图形 上篇
    Expression Tree上手指南 (一)
    用GPU通用并行计算绘制曼德勃罗特集图形 下篇
    .NET 4.0中的泛型协变和反变
    开发者眼里的WindowsPhone8的帐
    Win8 Metro App里玩XNA:框架问题解决方案
    Cocos2dx for WindowsPhone:一个按钮走天下
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7199907.html
Copyright © 2020-2023  润新知