zoukankan      html  css  js  c++  java
  • HDU3874 Necklace 树状数组+离线处理

    这题是要求一段区间内的不重复的数字之和。我们通过对询问区间的右端点进行排序,然后记录每一数字的上一次的出现的位置,由于询问都是不回溯的那么就可以线性的更新了。

    代码如下:

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MAXN 50005
    using namespace std;
    
    typedef long long int Int64;
    
    int N, M, seq[MAXN], last[1000005];
    
    Int64 ans[200005], c[MAXN];
    
    int lowbit(int x)
    {
        return x & -x;
    }
    
    void modify(int x, int val)
    {
        for (int i = x; i <= N; i += lowbit(i)) {
            c[i] += val;    
        }
    }
    
    Int64 sum(int x)
    {
        Int64 ret = 0;
        for (int i = x; i > 0; i -= lowbit(i)) {
            ret += c[i];
        }
        return ret;
    }
    
    struct Node
    {
        int a, b, no;
        bool operator < (Node temp) const
        {
            return b < temp.b;    
        }
    }q[200005];
    
    int main()
    {
        int T, ptr;
        scanf("%d", &T);
        while (T--) {
            memset(last, 0, sizeof (last));
            memset(c, 0, sizeof (c));
            scanf("%d", &N);
            ptr = 1;
            for (int i = 1; i <= N; ++i) {
                scanf("%d", &seq[i]);
            }
            scanf("%d", &M);
            for (int i = 1; i <= M; ++i) {
                scanf("%d %d", &q[i].a, &q[i].b);
                if (q[i].a > q[i].b) {
                    int t = q[i].a;
                     q[i].a = q[i].b;
                    q[i].b = t;
                }
                q[i].no = i;
            }
            sort(q+1, q+M+1);
            for (int i = 1; i <= M; ++i) {
                while (ptr <= q[i].b) {
                    if (last[seq[ptr]]) {
                        modify(last[seq[ptr]], -seq[ptr]);
                    }
                    last[seq[ptr]] = ptr;
                    modify(ptr, seq[ptr]);
                    ++ptr;
                }
                ans[q[i].no] = sum(q[i].b) - sum(q[i].a-1);
            }
            for (int i = 1; i <= M; ++i) {
                printf("%I64d\n", ans[i]);
            }
        }
        return 0;    
    }
  • 相关阅读:
    C++PRIMER 阅读笔记 第三章
    一个for循环打印二维数组
    递归实现数组求和
    strlen 与 sizeof
    call,apply,bind,this
    js 原型继承
    vue 动画
    vuex学习心得
    vue+elementui dropdown 下拉菜单绑定方法
    vue 生命周期一点学习
  • 原文地址:https://www.cnblogs.com/Lyush/p/2633467.html
Copyright © 2011-2022 走看看