zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    ref out param 区别
    SQL语句执行顺序以及oracle基本查询优化
    Ext.LoadMask遮罩的效果几种实现方式
    用ajax技术实现无闪烁定时刷新页面
    ExtJs 实现动态列,动态多表头 在这里添加日志标题
    Ajax中文乱码问题解决方法(服务器端用servlet)
    订购国际机票的常用指令
    ETERM航班销售控制指令
    线程wait()和sleep()的区别
    JSt中对象的prototype属性
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/15078733.html
Copyright © 2011-2022 走看看