现在的位置: 首页 > 综合 > 正文

HDU4638 Group

2013年10月13日 ⁄ 综合 ⁄ 共 1871字 ⁄ 字号 评论关闭

线段树。

将查询区间保存下来,按左端点由小到大排序。

在添加一个点a的时候:

  如果a+1和a-1都出现过,则点a连接了两个不同的group,group数量-1。

  如果a+1和a-1出现过一个,则点a进入了一个group,group数量不变。

  如果a+1和a-1都没出现过,则点a自己是一个group,group数量+1。

从头开始到某点的group变化数量的和就是最终的group数量。

在删除一个点a旁边的点的时候:

  如果a+1和a-1都没被删除,则点a不再连接两个不同的group,group数量变为0。

  如果a+1和a-1中有一个没删除,则点a成为独立的group,group数量变为+1。

两种情况变化都是多了一个group,所以删除的时候就是将旁边的点加1。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;

int n, m;
int a[MAXN], b[MAXN], pos[MAXN];
int ans[MAXN];
bool visit[MAXN];

struct SegmentTree
{
    int l, r, sum;
} tree[MAXN * 3];

void build(int x, int l, int r)
{
    tree[x].l = l;
    tree[x].r = r;
    if (l == r)
    {
        tree[x].sum = b[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(x << 1, l, mid);
    build((x << 1) + 1, mid + 1, r);
    tree[x].sum = tree[x << 1].sum + tree[(x << 1) + 1].sum;
}

void update(int x, int pos)
{
    ++tree[x].sum;
    if (tree[x].l == tree[x].r)
    {
        return;
    }
    int mid = (tree[x].l + tree[x].r) >> 1;
    if (pos <= mid)
    {
        update(x << 1, pos);
    }
    else
    {
        update((x << 1) + 1, pos);
    }
}

int query(int x, int l, int r)
{
    if (tree[x].l == l && tree[x].r == r)
    {
        return tree[x].sum;
    }
    int mid = (tree[x].l + tree[x].r) >> 1;
    if (r <= mid)
    {
        return query(x << 1, l, r);
    }
    else if (l > mid)
    {
        return query((x << 1) + 1, l, r);
    }
    return query(x << 1, l, mid) + query((x << 1) + 1, mid + 1, r);
}

struct Query
{
    int l, r;
    int index;
    friend bool operator <(const Query &a, const Query &b)
    {
        if (a.l == b.l)
        {
            return a.r > b.r;
        }
        return a.l < b.l;
    }
} queries[MAXN];

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d%d", &n, &m);
        memset(visit, 0, sizeof(visit));
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            int x = visit[a[i] - 1] + visit[a[i] + 1];
            if (x == 0)
            {
                b[i] = 1;
            }
            else if (x == 1)
            {
                b[i] = 0;
            }
            else
            {
                b[i] = -1;
            }
            visit[a[i]] = true;
            pos[a[i]] = i;
        }
        build(1, 1, n);
        for (int i = 0; i < m; ++i)
        {
            queries[i].index = i;
            scanf("%d%d", &queries[i].l, &queries[i].r);
        }
        sort(queries, queries + m);
        int left = 1;
        for (int i = 0; i < m; ++i)
        {
            while (left < queries[i].l)
            {
                if (a[left] - 1 >= 1)
                {
                    update(1, pos[a[left] - 1]);
                }
                if (a[left] + 1 <= n)
                {
                    update(1, pos[a[left] + 1]);
                }
                ++left;
            }
            ans[queries[i].index] = query(1, queries[i].l, queries[i].r);
        }
        for (int i = 0; i < m; ++i)
        {
            printf("%d\n", ans[i]);
        }
    }
    return 0;
}

抱歉!评论已关闭.