zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 数据结构-线段树+区间离散化(POJ2528)

      这道题用线段树做更方便更新和查询,但是其数据范围很大,因此要将离散化和线段树结合起来,算是一道比较经典的线段树+离散化的例题。

    线段树的离散化有很多方法,在这里,我先用一次结点离散化,间接将源左右端点离散化的想法实现。(受到一个博客的启发)


      题意:贴海报-给出海报左右端点,然后顺序贴上,问最后有多少海报可见。

      直接贴上Code,具体解释在注释中有提及(有不懂的地方可以在纸上打个线段树草稿试试):

    //贴海报-给出海报左右端点,顺序贴上,问最后有多少海报可见。
    //Time:79Ms	Memory:2712K
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    #define MAX 10005
    
    struct Node {
    	int l, r, kind;
    }tr[16*MAX];	//两端点加空点需要8-16*MAX数据量
    
    struct Pos {
    	int num, id;
    	friend bool operator < (Pos p1, Pos p2) { return p1.num < p2.num; }
    }pos[2*MAX];
    
    int n, cnt;
    int l[MAX], r[MAX];
    bool v[MAX];
    
    void build(int x,int l,int r)
    {
    	tr[x].l = l;	tr[x].r = r;
    	if (l == r)	return;
    	int mid = (l + r) / 2;
    	build(2 * x, l, mid);
    	build(2 * x + 1, mid + 1, r);
    }
    
    void update(int x,int l,int r,int k)
    {
    	if (tr[x].l == l && tr[x].r == r) {
    		tr[x].kind = k;
    		return;
    	}
    	if (tr[x].kind) {
    		tr[2 * x].kind = tr[x].kind;
    		tr[2 * x + 1].kind = tr[x].kind;
    		tr[x].kind = 0;
    	}
    	int mid = (tr[x].l + tr[x].r) / 2;
    	if (r <= mid)	update(2 * x, l, r, k);
    	else if (l > mid)	update(2 * x + 1, l, r, k);
    	else {
    		update(2 * x, l, mid, k);
    		update(2 * x + 1, mid + 1, r, k);
    	}
    }
    
    int query(int x,int l,int r)
    {
    	if (tr[x].kind) {
    		if (v[tr[x].kind])	return 0;
    		else { v[tr[x].kind] = true; return 1;}
    	}
    	if (tr[x].l == tr[x].r) return 0;	//由于有空点,可能会有tr[x].kind = 0
    	int mid = (tr[x].l + tr[x].r) / 2;
    	return query(2 * x, l, mid) + query(2 * x + 1, mid + 1, r);
    }
    
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	while (T--) {
    		memset(tr, 0, sizeof(tr));
    		memset(v, 0, sizeof(v));
    		scanf("%d", &n);
    		for (int i = 0; i < n; i++)
    		{
    			scanf("%d%d", &l[i], &r[i]);
    			pos[2 * i].num = l[i];
    			pos[2 * i + 1].num = r[i];
    			pos[2 * i].id = 2 * i;	//偶数-左端点
    			pos[2 * i + 1].id = 2 * i + 1;	//奇数-右端点
    		}
    		int last = pos[0].num;
    		cnt = 1;
    		sort(pos, pos + 2 * n);
    		for (int i = 0; i < 2 * n; i++)
    		{
    			if (last != pos[i].num) {
    				if (pos[i].num - last > 1)	
    					cnt++;	//不相邻时,中间空一点
    				cnt++;
    				last = pos[i].num;
    			}
    			int id = pos[i].id;	//分别对左右端点离散化
    			id % 2 ? r[id/2] = cnt : l[id/2] = cnt;
    		}
    		build(1, 1, cnt);
    		for (int i = 0; i < n; i++)
    			update(1, l[i], r[i], i + 1);
    		printf("%d
    ", query(1, 1, cnt));
    	}
    	
    	return 0;
    }
    
    他坐在湖边,望向天空,她坐在对岸,盯着湖面
  • 相关阅读:
    解决方案下显示的网站名称被追加编号的问题解决方法
    sql server 2008 报表服务器(sql server 2008 report service)中如何固定行或者列
    如何通过参数来切换图表和数据
    饼图中如何将一定比例的小切片收集在一起
    饼图图例中显示百分比值
    如何根据条件隐藏列
    饼图上如何显示百分比值
    负载均衡
    在UTF8页中接收和使用以GB2312方式进行URL编码的中文数据
    ASP 格式化显示时间为几个月,几天前,几小时前,几分钟前,或几秒前
  • 原文地址:https://www.cnblogs.com/Inkblots/p/4937187.html
Copyright © 2011-2022 走看看