POJ 2528 Mayor's posters (线段树+离散化)

题目链接:ヽ(ˋ▽ˊ)ノ


哎~网上看了老久,才知道怎么离散化,郁闷,建树前需要离散化点, 用p[i][2]来存储每个点离散化前的信息, 用结构体num来存储每个点的具体信息


code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
	int num, id , left;//该点的数值, 为哪条线段的, 左端点还是右端点
}node;
node num[2*20005];
struct Tnode
{
	int left, right, color;
}tree[4*20005];
int p[10005][2], sum = 0, flag[20005];


int cmp( const void *a ,const void *b)
{
	return (*(node *)a).num>(*(node *)b).num?1:-1;
}
void build(int root, int left, int right)
{
	int mid = (left+right)/2;
	if(left == right)
	{
		tree[root].left = tree[root].right = left;
		tree[root].color = 0;
		return ;
	}
	tree[root].left = left; tree[root].right = right; tree[root].color = 0;
	build(2*root, left, mid);
	build(2*root+1, mid+1, right);
}

void insert(int root, int left, int right, int color)
{
	int mid = (tree[root].left+tree[root].right)/2;
	if(tree[root].left == left && tree[root].right == right)
	{
		tree[root].color = color;
		return ;
	}
	if(tree[root].color)
	{
		tree[2*root].color = tree[root].color;
		tree[2*root+1].color = tree[root].color;
		tree[root].color = 0;
	}
	if(right<=mid)
		insert(2*root, left, right, color);
	else if(left>mid)
		insert(2*root+1, left, right, color);
	else
	{
		insert(2*root, left, mid, color);
		insert(2*root+1, mid+1, right, color);
	}
}
 void query(int root)
 {
 	if(tree[root].color)
 	{
 		if(!flag[tree[root].color])
 		{
 			flag[tree[root].color] = 1;
 			sum++;
 		}
 		return ;
 	}
 	query(2*root);
 	query(2*root+1);
 }
int main()
{
	int i = 0, n = 0, t = 0, k = 0, pre = 0, index = 0;
	scanf("%d",&t);
	while(t--)
	{
		k = 0;
		scanf("%d",&n);
		for(i = 0; i<n; i++)
		{
			scanf("%d %d",&p[i][0], &p[i][1]);
			num[k].num = p[i][0];//用num来存储该点的信息有为第几段, 端点位, 数值
			num[k].id = i;
			num[k++].left = 1;
			num[k].num = p[i][1];
			num[k].id = i;
			num[k++].left = 0;
		}
		qsort(num, k, sizeof(num[0]), cmp);//对结构体中的数值排序
		pre = -1; index = 0;//用index来确定离散化后的范围
		for(i = 0; i<2*n; i++)
		{
			if(num[i].num != pre)//不是重复的点范围加一
			{
				index++;
				pre = num[i].num;
			}
			if(num[i].left)
				p[num[i].id][0] = index;
			else
				p[num[i].id][1] = index;
		}//离散化完毕
		build(1, 1, index);
		for(i = 0; i<n; i++)
			insert(1, p[i][0], p[i][1], i+1);//对线段进行上色
		sum = 0;
		memset(flag, 0, sizeof(flag));//判重
		query(1);
		printf("%d\n",sum);
	}
	return 0;
}

code:简单点的离散化



离散化时注意相邻两点的离散化

数据

1 10 

1 3 

6 10

不能离散化成4个点, 要离散化为5个点, 应为3与6在没离散化前是图了色的, 离散化完后不能忽略了这个区间

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sum = 0, p[10005][2],  num[20005], num1[100005], tree[50005*6], used[100005];
int cmp(const void *a, const void *b)
{
	return *(int *)a-*(int *)b;
}
void build(int root, int left, int right)
{
	int mid = (left+right)/2;
	if(left == right)
	{
		tree[root] = 0;
		return;
	}
	tree[root] = 0;
	build(2*root, left, mid);
	build(2*root+1, mid+1, right);
}
void insert(int root, int left, int right, int start, int end, int col)
{
	int mid = (left+right)/2;
	if(num1[left] >= start && num1[right] <= end)
	{
		tree[root] = col;
		return ;
	}
	if(tree[root] != 0)
	{
		tree[2*root] = tree[2*root+1] = tree[root];
		tree[root] = 0;
	}
	if(num1[mid]>=start)
		insert(2*root, left, mid, start, end, col);
	if(num1[mid]<end)
		insert(2*root+1, mid+1, right, start, end, col);
}
void query(int root, int left, int right)
{
	int col = tree[root], mid = (left+right)/2;
	if(col != 0)
	{
		if(!used[col])
		{
			used[col] = 1;
			sum++;
		}
		return ;
	}
	if(left == right)
		return;
	query(2*root, left, mid);
	query(2*root+1, mid+1, right);
}
int main()
{
	int t = 0, i = 0, n = 0, k = 0, index = 0, pre = -1;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		k = 1;
		for(i = 0; i<n; i++)
		{
			scanf("%d %d",&p[i][0], &p[i][1]);
			num[k++] = p[i][0];
			num[k++] = p[i][1];
		}
		num[0] = 0;
		qsort(num, k, sizeof(num[0]), cmp);
		pre = -1; index = 1;
		num[0] = num[1];
		for(i = 1; i<k; i++)
		{
			if(num[i]-num[i-1]>1)
				num1[index++] = num[i]-1;
			if(num[i] != pre)
			{
				num1[index++] = num[i];
				pre = num[i];
			}
		}
		build(1, 1, index-1);
		//memset(tree, 0, 6*index*sizeof(tree[0]));
		memset(used,0,sizeof(used));
		for(i = 0; i<n; i++)
			insert(1, 1, index-1, p[i][0], p[i][1], i+1);
		sum = 0;
		query(1, 1, index-1);
		printf("%d\n",sum);
	}
	return 0;
}



这代码错的也能过...........

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 20002
using namespace std;
struct node
{
    int x, y;
}p[N];
int cnt = 0, ans = 0, id = 0, X[2*N], t[3*N], used[N];

void update(int c, int l, int r, int lf, int rt, int col)
{
    int m = l+(r-l)/2;
    if(lf<=X[l] && rt>=X[r])
    {
        t[c] = col;
        return ;
    }
    if(t[c])
    {
        t[2*c] = t[2*c+1] = t[c];
        t[c] = 0;
    }
    if(lf<=X[m]) update(2*c, l, m, lf, rt, col);
    if(rt>X[m]) update(2*c+1, m+1, r, lf, rt, col);
}

void query(int c, int l, int r)
{
    int m = l+(r-l)/2;
    if(t[c] && !used[t[c]])
    {
        ans++;
        used[t[c]] = 1;
    }
    if(t[c]) return ;
    if(l == r)
        return ;
    query(2*c, l, m);
    query(2*c+1, m+1, r);
}


int main()
{
    //freopen("input.txt", "r", stdin);
    int i = 0, c = 0, n = 0;
    scanf("%d", &c);
    while(c--)
    {
        memset(used, 0, sizeof(used));
        memset(t, 0, sizeof(t));
        cnt = ans = 0;
        scanf("%d", &n);
        for(i = 0; i<n; i++)
        {
            scanf("%d %d", &p[i].x, &p[i].y);
            X[cnt++] = p[i].x;
            X[cnt++] = p[i].y;
        }
        sort(X, X+cnt);
        cnt = unique(X, X+cnt)-X;
        for(i = 0; i<n; i++)
            update(1, 0, cnt-1, p[i].x, p[i].y, i+1);
        query(1, 0, cnt-1);
        printf("%d\n", ans);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值