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;    
    }
  • 相关阅读:
    正则表达式
    js 联系电话验证实现
    curl 解析
    WinRAR打包时不包含文件夹本身,只打包文件夹里的文件和目录
    如何判断事务是否完成,SqlTransaction
    循环枚举的名称或值
    FileStream 和StreamWriter 一起用时
    ToString yyyy-MM-dd ,MM 小写的故事。
    用7z.exe 压缩整个文件夹里的内容
    VS2010安装选项中有个“图标库”
  • 原文地址:https://www.cnblogs.com/Lyush/p/2633467.html
Copyright © 2011-2022 走看看