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

来源:互联网 发布:ps4黑色星期五知乎 编辑:程序博客网 时间:2024/04/30 11:53

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


哎~网上看了老久,才知道怎么离散化,郁闷,建树前需要离散化点, 用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;elsep[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 20002using 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;}