• 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
    ", query(T[r], l));
            }
        }
        return 0;
    }
    


  • 相关阅读:
    SSH
    List Map Set
    oracle中的in和exsit比较
    Hibernate n+1问题
    单例模式。
    把一段逗号分割的字符串转换成一个数组
    Hibernate总结
    myeclipse安装svn插件的多种方式
    LeetCode 14 Longest Common Prefix
    LeetCode 13 Roman to Integer
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3358195.html
Copyright © 2020-2023  润新知