poj2528 线段树+离散化(贴海报)

对于这道题首先要用到离散化的知识,但是离散化并非常规的离散化。

离散化,如下面的例子(题目的样例),因为单位1是一个单位长度,将下面的

      1   2   3   4  6   7   8   10

     —  —  —  —  —  —  —  —

      1   2   3   4  5   6   7   8

离散化  X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] = 8; X[8] = 10

于是将一个很大的区间映射到一个较小的区间之中了,然后再对每一张海报依次更新在宽度为1~8的墙上(用线段树),最后统计不同颜色的段数。

但是只是这样简单的离散化是错误的,

如三张海报为:1~10 1~4 6~10

离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。

新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)

X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10

这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3

最终,1~2为2,3为1,4~5为3,于是输出正确结果3。

至于贴海报, 要倒着思考 注意线段树开的空间大小。poj用c++过不了,用G++可以过,不知道为什么

关于离散化的一个叫做区间离散化的东西也很容易出错需要注意。

#include<iostream>
#include<string>
#include <cstdlib>
#include <algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include <iomanip>

// #pragma comment(linker, "/STACK:1024000000,1024000000")
// #define pi acos(-1)
// #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define INF 0x7f7f7f7f //2139062143
#define INF1 0x3f3f3f3f //1061109567
#define INF2 2147483647
#define llINF 9223372036854775807
#define pi 3.141592653589793//23846264338327950254
#define pb push_back
#define ll long long
#define debug cout << "debug
";
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// ios::sync_with_stdio(false);cin.tie(NULL);
#define scai(x) scanf("%d", &x)
#define sca2i(x, y) scanf("%d %d", &x, &y)
#define scaf(x) scanf("%lf", &x)
#define sca2f(x, y) scanf("%lf %lf", &x, &y)
#define For(m,n) for (int i = m;  i < n; i++)

#define local
#ifdef local
#endif

#define MAX 10233
#define LCH(i) ((i) << 1)
#define RCH(i) ((i) << 1 | 1)

int X[MAX][2];
int lsh[MAX<<1];

struct node
{
    int l, r;
    int lazy;
}tree[MAX<<3];

void build(int rt, int l, int r)
{
    // debug
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].lazy = 0;
    if (l == r)
    {
        return;
    }
    int mid = (l + r) >> 1;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid + 1, r);

}

bool updata(int rt, int l, int r)
{
    if (tree[rt].lazy)
    {
        return false;
    }
    else if (tree[rt].l == l && tree[rt].r == r)
    {
        tree[rt].lazy = 1;
        return true;
    }
    int mid = (tree[rt].l + tree[rt].r) >> 1;
    bool flag;
    if (r <= mid)
    {
        flag = updata(rt<<1, l, r);
    }
    else if (l > mid)
    {
        flag = updata(rt<<1|1, l, r);
    }
    else
    {
        bool flag1 = updata(rt<<1, l, mid);
        bool flag2 = updata(rt<<1|1, mid + 1, r);
        flag = flag1 || flag2;
    }
    if (tree[rt << 1].lazy == 1 && tree[rt << 1|1].lazy == 1)
        tree[rt].lazy = 1;
        return flag;

}
int main()
{
    int Case;
    scanf("%d
", &Case);
    while(Case--)
    {
        int n;
        scanf("%d", &n);
        int k = 0;
        for (int i = 0; i < n; i++)
        {
            scanf("%d%d", &X[i][0], &X[i][1]);
            lsh[k++] = X[i][0];
            lsh[k++] = X[i][1];
        }
        sort(lsh, lsh + k);
        int size = unique(lsh, lsh + k) - lsh;
        k = size;
        for (int i = 0; i < size; i++)
        {
            if (lsh[i] - lsh[i-1] > 1)
                lsh[k++] = lsh[i] + 1;
        }
        size = k;
        sort(lsh, lsh + size);
        build(1, 0, size - 1);

        int ans = 0;
        for (int i = n-1; i >= 0; i--)
        {
            int l = lower_bound(lsh, lsh + size, X[i][0]) - lsh;
            int r = lower_bound(lsh, lsh + size, X[i][1]) - lsh;
            if (updata(1, l, r))
                ans++;
        }
        printf("%d
", ans);
    }
}
原文地址:https://www.cnblogs.com/hulian425/p/12233501.html