• HDU


    题目链接

    题目大意

      询问区间内满足(c xor a < b)的不同的数的个数。

    解题思路

      求区间不同的数可以用树状数组离线来做,求满足(c xor a < b)的数可以用字典树来做,树状数组的每一个节点开一个字典树即可。算是两种思路的结合吧。

    const int maxn = 1e5+10;
    const int maxm = maxn*400;
    int n, m, a[maxn];
    int tr[maxm][2], cnt[maxm], idx;
    int c[maxn], rt[maxn], lst[maxn], ans[maxn];
    struct INFO {
        int l, a, b, i;
    };
    vector<INFO> q[maxn];
    void insert(int &p, int v, int x) {
        if (!p) p = ++idx;
        int now = p; //不能用p往下走,因为上面是引用
        for (int i = 20; i>=0; --i) {
            int t = x>>i&1;
            if (!tr[now][t]) tr[now][t] = ++idx;
            now = tr[now][t];
            cnt[now] += v;
        }
    }
    void add(int x, int v, int y) {
        while(x<=n) {
            insert(rt[x], v, y);
            x += x&-x;
        }
    }
    int query(int p, int a, int b) {
        int sum = 0;
        for (int i = 20; i>=0; --i) {
            int t1 = a>>i&1;
            int t2 = b>>i&1;
            /*
                a   b
                1   1   1++ 0
                0   1   0++ 1
                1   0   1
                0   0   0
            */
            if (t2) {
                if (t1) sum += cnt[tr[p][1]], p = tr[p][0];
                else sum += cnt[tr[p][0]], p = tr[p][1];
            }
            else {
                if (t1) p = tr[p][1];
                else p = tr[p][0];
            }
            if (!p) break;
        }
        return sum+cnt[p];
    }
    int ask(int x, int a, int b) {
        int sum = 0;
        while(x) {
            sum += query(rt[x], a, b);
            x -= x&-x;
        }
        return sum;
    }
    int main() {
        IOS;
        cin >> n;
        for (int i = 1; i<=n; ++i) cin >> a[i];
        cin >> m;
        for (int i = 1; i<=m; ++i) {
            int l, r, c, d; cin >> l >> r >> c >> d;
            q[r].push_back({l, c, d, i});
        }
        for (int i = 1; i<=n; ++i) {
            if (lst[a[i]]) add(lst[a[i]], -1, a[i]);
            add(i, 1, a[i]);
            //for (int j = 1; j<=n; ++j) cout << rt[j] << endl;
            lst[a[i]] = i;
            for (auto v : q[i]) ans[v.i] = ask(i, v.a, v.b)-ask(v.l-1, v.a, v.b);
        }
        for (int i = 1; i<=m; ++i) cout << ans[i] << endl;
        return 0;
    }
    
  • 相关阅读:
    分布式缓存技术之Redis_03分布式redis
    Spring 二、400行代码手写初体验Spring V1.0版本
    Spring 一、各级架构与依赖关系
    Java正则表达式基础学习
    JAVA开发:SpringBoot多数据源配置
    Spring 单例模式实现源码分析
    Spring 使用的设计模式用哪些
    Spring之@Autowired和@Resource
    Spring的优缺点
    MySQL支持的事物隔离级别以及悲观锁和乐观锁原理和应用场景
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/15078733.html
Copyright © 2020-2023  润新知