HDU 5722 Jewelry

矩形面积并。

需要转化一下思路:记录每一个位置的数以及位置。

对数字进行从小到大排序,数字一样的按位置从小到大排。

这样,一样的数就在一起了。连续的相同的x个数就可以构成很多解,这些解对应于二维平面上某矩形内整点个数(包括边界)。

这样就处理出很多很多的矩形,因为重复只能计算一次,所以可以采用矩形面积并计算。

PS:计算整点个数的话,可以讲每一个矩形的左下角左边-1 -1,这样就直接当面积来算就可以了。

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1

const long long maxn = 200000 + 10;
struct XX
{
    long long num;
    long long pos;
}s[maxn];
long long cnt[maxn << 2];
long long sum[maxn << 2];
long long X[maxn];
struct Seg {
    long long h, l, r;
    long long s;
    Seg(){}
    Seg(long long a, long long b, long long c, long long d) : l(a), r(b), h(c), s(d) {}
    bool operator < (const Seg &cmp) const {
        return h < cmp.h;
    }
}ss[maxn];
void PushUp(long long rt, long long l, long long r) {
    if (cnt[rt]) sum[rt] = X[r + 1] - X[l];
    else if (l == r) sum[rt] = 0;
    else sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void update(long long L, long long R, long long c, long long l, long long r, long long rt) {
    if (L <= l && r <= R) {
        cnt[rt] += c;
        PushUp(rt, l, r);
        return;
    }
    long long m = (l + r) >> 1;
    if (L <= m) update(L, R, c, lson);
    if (m < R) update(L, R, c, rson);
    PushUp(rt, l, r);
}
long long Bin(long long key, long long n, long long X[]) {//离散化
    long long l = 0, r = n - 1;
    while (l <= r) {
        long long m = (l + r) >> 1;
        if (X[m] == key) return m;
        if (X[m] < key) l = m + 1;
        else r = m - 1;
    }
    return -1;
}
bool cmp(const XX&a, const XX&b)
{
    if (a.num == b.num) return a.pos<b.pos;
    return a.num<b.num;
}
int main() {
    long long T, sz, h;
    scanf("%lld", &T);
    while (T--){

        scanf("%lld%lld", &sz, &h);
        for (long long i = 1; i <= sz; i++)
        {
            scanf("%lld", &s[i].num);
            s[i].pos = i;
        }

        sort(s + 1, s + 1 + sz, cmp);

        long long m = 0;

        for (long long i = 1; i <= sz; i++)
        {
            if (i + h - 1>sz) break;
            if (s[i].num != s[i + h - 1].num) continue;

            long long Lmin, Lmax, Rmin, Rmax;

            if (i == 1 || s[i - 1].num != s[i].num) Lmin = 1;
            else Lmin = s[i - 1].pos + 1;
            Lmax = s[i].pos;

            Rmin = s[i + h - 1].pos;
            if (i + h -1 == sz || s[i + h].num != s[i + h - 1].num) Rmax = sz;
            else Rmax = s[i + h].pos - 1;

            long long x1 = Lmin - 1, y1 = Rmin - 1, x2 = Lmax, y2 = Rmax;

            long long a = x1, b = y2, c = x2, d = y1;
            X[m] = a;
            ss[m++] = Seg(a, c, b, 1);
            X[m] = c;
            ss[m++] = Seg(a, c, d, -1);
        }

        sort(X, X + m);
        sort(ss, ss + m);
        long long k = 1;
        for (long long i = 1; i < m; i++) {
            if (X[i] != X[i - 1]) X[k++] = X[i];
        }
        memset(cnt, 0, sizeof(cnt));
        memset(sum, 0, sizeof(sum));
        long long ret = 0;
        for (long long i = 0; i < m - 1; i++) {
            long long l = Bin(ss[i].l, k, X);
            long long r = Bin(ss[i].r, k, X) - 1;
            if (l <= r) update(l, r, ss[i].s, 0, k - 1, 1);
            ret += sum[1] * (ss[i + 1].h - ss[i].h);
        }
        printf("%lld\n", ret);
    }
    return 0;
}

 

posted @ 2016-07-21 22:30  Fighting_Heart  阅读(231)  评论(0编辑  收藏  举报