zoukankan      html  css  js  c++  java
  • POJ 2528 Mayor's posters 离散化和线段树题解

    本题就是要往墙上贴海报,问最后有多少可见的海报。

    事实上本题的难点并非线段树,而是离散化。

    由于数据非常大,直接按原始数据计算那么就会爆内存和时间的。

    故此须要把数据离散化。

    比方有海报1 6   7 9   20 100  5 1000的原始数据。直接计算须要1-1000的内存,离散化之后仅仅须要8内存,由于仅仅有4组数据8个数。

    本题更进一步高级一点的离散化就是须要把不相邻的两个数据插入一个数值。表示有空白的地方,不是全部海报都覆盖到的。

    比方上面的数据要离散为:1 2  5 6  7 8 9 10 20 21 100 101 1000,中间插入了一些数值,这样才干保证数据正确。

    比較难想出来的地方。须要好好考虑一下才干想通的。

    看程序discreteArr是离散化之后的数据。使用这种数据处理就能够比原始数据少非常多数据了。


    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int SIZE = 10005;
    bool hashColor[SIZE];
    int le[SIZE], ri[SIZE];
    int discreteArr[SIZE<<2];//由于这里或许须要四倍的SIZE内存
    int seg[SIZE<<4];
    int visiblePosts;
    
    inline int lChild(int rt) { return rt<<1; }
    inline int rChild(int rt) { return rt<<1|1; }
    
    inline void pushDown(int rt)
    {
    	if (seg[rt])
    	{
    		seg[lChild(rt)] = seg[rChild(rt)] = seg[rt];
    		seg[rt] = 0;
    	}
    }
    
    void build(int l, int r, int rt)
    {
    	seg[rt] = 0;
    	if (l == r) return ;
    	int m = l + ((r-l)>>1);
    	build(l, m, lChild(rt));
    	build(m+1, r, rChild(rt));
    }
    
    void update(int ql, int qr, int col, int l, int r, int rt)
    {
    	if (ql <= l && r <= qr)
    	{
    		seg[rt] = col;
    		return;
    	}
    	pushDown(rt);
    	int m = l + ((r-l)>>1);
    	if (ql <= m) update(ql, qr, col, l, m, lChild(rt));
    	if (m < qr) update(ql, qr, col, m+1, r, rChild(rt));
    }
    
    void query(int l, int r, int rt)
    {
    	if (seg[rt])
    	{
    		if (!hashColor[seg[rt]])
    		{
    			visiblePosts++;
    			hashColor[seg[rt]] = true;
    		}
    		return ;
    	}
    	if (l == r) return ;//注意这里没有poster的时候
    	int m = l + ((r-l)>>1);
    	query(l, m, lChild(rt));
    	query(m+1, r, rChild(rt));
    }
    
    int biSearch(int arr[], int key, int n)
    {
    	int l = 1, r = n-1, m = -1;
    	while (l <= r)
    	{
    		m = l + ((r-l)>>1);
    		if (arr[m] < key) l = m+1;
    		else if (key < arr[m]) r = m-1;
    		else break;
    	}
    	return m;
    }
    
    int main()
    {
    	int T, n;
    	scanf("%d", &T);
    	while (T--)
    	{
    		scanf("%d", &n);
    		int disN = 1;
    		for (int i = 1; i <= n; i++)
    		{
    			scanf("%d %d", &le[i], &ri[i]);
    			discreteArr[disN++] = le[i];
    			discreteArr[disN++] = ri[i];
    		}
    		sort(discreteArr+1, discreteArr+disN);
    
    		int j = 2;
    		for (int i = 2; i < disN; i++)
    		{
    			if (discreteArr[i] != discreteArr[i-1]) 
    				discreteArr[j++] = discreteArr[i];
    		}
    		for (int i = j-1; i > 1; i--)
    		{
    			if (discreteArr[i] != discreteArr[i-1] + 1)
    				discreteArr[j++] = discreteArr[i-1] + 1;
    		}
    		sort(discreteArr + 1, discreteArr + j);
    		build(1, j-1, 1);
    		for (int i = 1; i <= n; i++)
    		{
    			int ql = biSearch(discreteArr, le[i], j);
    			int qr = biSearch(discreteArr, ri[i], j);
    			update(ql, qr, i, 1, j-1, 1);
    		}
    		visiblePosts = 0;
    		memset(hashColor, 0, sizeof(bool) * (n+1));
    		query(1, j-1, 1);
    		printf("%d
    ", visiblePosts);
    	}
    	return 0;
    }
    
    
    


  • 相关阅读:
    安全探讨之用Win32汇编写双进程守护
    LightTPD 1.4.12
    mysql4存在mysql5没有的性能成绩
    gcolor2-拾色器
    solaris 中挂载usb移动硬盘
    Browsershots:测试你的 Web 企图
    MythTV 0.20
    XorgEdit:xorg.conf 编纂器
    pci168c,1c无线网卡如何在64位Solaris系统上运用
    Fedora8中批改磁盘卷标
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6925802.html
Copyright © 2011-2022 走看看