zoukankan      html  css  js  c++  java
  • HDU

    题目链接

    题目大意

      询问区间[l,r]中满足相邻两个树大小不超过k的数对。

    解题思路

      如果一个一个加入数字的话,设当前数字为i,那么对答案的贡献就是之前的数字之中([a_i-k,a_i+k])范围内的数字的数量,可以用莫队来维护l,r,然后每次的修改和查询操作用树状数组来操作。

    代码

    const int maxn = 1e5+10;
    const int maxm = 1e6+10;
    int n, nn, m, k;
    int a[maxn], b[maxn], p[maxn];
    int find(int x) {
        return lower_bound(b+1, b+nn+1, x)-b;
    }
    int find2(int x) {
        return upper_bound(b+1, b+nn+1, x)-b;
    }
    int c[maxn];
    void insert(int x, int y) {
        while(x<=n) {
            c[x] += y;
            x += x&-x;
        }
    }
    int ask(int x) {
        int sum = 0;
        while(x) {
            sum += c[x];
            x -= x&-x;
        }
        return sum;
    }
    struct Q {
        int l, r, i;
    } q[maxn];
        int l = 1, r = 0;
    int ans[maxn], res, up[maxn], low[maxn];
    void add(int x) {
        res += ask(up[x])-ask(low[x]-1);
        insert(a[x], 1);
    }
    void sub(int x) {
        insert(a[x], -1);
        res -= ask(up[x])-ask(low[x]-1);
        //cout << a[x] << ' ' << l << ' ' << r << ' ' << res << endl;
    }
    int main() {
        IOS;    
        cin >> n >> m >> k;
        for (int i = 1; i<=n; ++i) cin >> a[i], b[i] = a[i];
        sort(b+1, b+n+1);
        nn = unique(b+1, b+n+1)-b-1;
        for (int i = 1; i<=n; ++i) {
            low[i] = find(a[i]-k);
            up[i] = find2(a[i]+k)-1;
            a[i] = find(a[i]);
            //cout << low[i] << ' ' << a[i] << ' ' << up[i] << endl;
        }
        for (int i = 1; i<=m; ++i) {
            cin >> q[i].l >> q[i].r;
            q[i].i = i;
        }
        int sz = sqrt(m)+1;
        sort(q+1, q+m+1, [=](Q x, Q y) {return (x.l/sz^y.l/sz) ? x.l/sz<y.l/sz : ((x.l/sz)%2 ? x.r<y.r:x.r>y.r);});
        for (int i = 1; i<=m; ++i) {
            //cout << q[i].l << ' ' << q[i].r << endl;
            while(q[i].r > r) add(++r);
            //cout << res << endl;
            while(q[i].l > l) sub(l++);
            //cout << res << endl;
            while(q[i].r < r) sub(r--);
            //cout << res << endl;
            while(q[i].l < l) add(--l);
            //cout << res << endl;
            ans[q[i].i] = res;
        }
        for (int i = 1; i<=m; ++i) cout << ans[i] << endl;
        return 0;
    }
    
  • 相关阅读:
    (二)php的常量和变量
    关于标签系统的一点想法。
    Linux运维工程师中级面试题
    Linux C 编程内存泄露检测工具(一):mtrace
    掌握sudo的使用
    Scala极速入门
    处理千万级以上的数据提高查询速度的方法
    linux svn服务器搭建、客户端操作、备份与恢复
    select/poll/epoll 对比
    汇编指令和标志寄存器
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/15041451.html
Copyright © 2011-2022 走看看