SPOJ DQUERY 求区间内不同数的个数 主席树


这题跟HDU3333差不多吧。

离线的做法很简单,不再说了

以前做过。



主席树的做法就比较暴力了。。


什么是主席树呢。。

其实是某种称号。

在该题中的体现是可持久化的线段树。

对于一个数

如果以前没出现过

就插入到主席树中

否则就删除以前那个。

再插入主席树。

注意,所有的更新和删除都是建立了新的节点来保持其历史状态的。。

对于T[i]我们存的是从1到i区间的不同的数出现了多少个。

然后这棵树是根据T[i - 1]来建立的。


代码如下。。第一次写主席树。 几乎是照着爱将的代码写的。

不过他是倒着来插入的,我是正向来的。 无非是一个以左端点为根查询。一个以询问的右端点为根查询,


 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <string>

#include <map>

#include <vector>

#include <algorithm>

#define INF 111111111

#define MAXN 33333

#define MAXM 600005

using namespace std;

int n, tot, q, a[MAXN];

int T[MAXM], lson[MAXM], rson[MAXM], val[MAXM];

int nxt[MAXN], b[MAXN];

int build(int l, int r)

{

    int rt = tot++;

    val[rt] = 0;

    int m = (l + r) >> 1;

    if(l != r)

    {

        lson[rt] = build(l, m);

        rson[rt] = build(m + 1, r);

    }

    return rt;

}

int update(int rt, int pos, int v)

{

    int newrt = tot++, tmp = newrt;

    int l = 1, r = n;

    val[newrt] = val[rt] + v;

    while(l < r)

    {

        int m = (l + r) >> 1;

        if(pos <= m)

        {

            lson[newrt] = tot++;

            rson[newrt] = rson[rt];

            newrt = lson[newrt];

            rt = lson[rt];

            r = m;

        }

        else

        {

            rson[newrt] = tot++;

            lson[newrt] = lson[rt];

            newrt = rson[newrt];

            rt = rson[rt];

            l = m + 1;

        }

        val[newrt] = val[rt] + v;

    }

    return tmp;

}



int query(int rt, int pos)

{

    int ret = 0;

    int l = 1, r = n;

    while(pos > l)

    {

        int m = (l + r) >> 1;

        if(pos <= m)

        {

            ret += val[rson[rt]];

            rt = lson[rt];

            r = m;

        }

        else

        {

            l = m + 1;

            rt = rson[rt];

        }

    }

    return ret + val[rt];

}

int main()

{

    while(scanf("%d", &n) != EOF)

    {

        tot = 0;

        memset(nxt, -1, sizeof(nxt));

        for(int i = 1; i <= n; i++)

        {

            scanf("%d", &a[i]);

            b[i - 1] = a[i];

        }

        sort(b, b + n);

        int cnt = unique(b, b + n) - b;

        T[0] = build(1, n);

        for(int i = 1; i <= n; i++)

        {

            int id = lower_bound(b, b + cnt, a[i]) - b;

            if(nxt[id] == -1)

                T[i] = update(T[i - 1], i, 1);

            else

            {

                int t = update(T[i - 1], nxt[id], -1);

                T[i] = update(t, i, 1);

            }

            nxt[id] = i;

        }

        scanf("%d", &q);

        while(q--)

        {

            int l, r;

            scanf("%d%d", &l, &r);

            printf("%d\n", query(T[r], l));

        }

    }

    return 0;

}


 

 

你可能感兴趣的:(query)