zoukankan      html  css  js  c++  java
  • HDU 3333 Turing Tree --树状数组+离线处理

    题意:统计一段序列【L,R】的和,重复元素只算一次。

    解法:容易看出在线做很难处理重复的情况,干脆全部讲查询读进来,然后将查询根据右端点排个序,然后离散化数据以后就可以操作了。

    每次读入一个数,如果这个数之前出现过,那么删除之前出现的那个数,改加上这个数,然后进行所有右端点小于等于此时下标的查询即可。

    关于正确性,引用sdj222555的话来说,"观察一个区间,我们可以发现,如果出现重复的,尽量删除左边的,保留右边的,那么右端点相同的区间都可以进行查询。"

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #define lll __int64
    using namespace std;
    #define N 30007
    
    lll c[N],ans[3*N+10004];
    map<int,int> mp;
    int a[N],pos[N],n,b[N],d[N];
    struct Query
    {
        int L,R,ind;
    }Q[3*N+10004];
    
    int cmp(Query ka,Query kb)
    {
        return ka.R < kb.R;
    }
    
    inline int lowbit(int x) { return x&(-x); }
    
    void modify(int pos,lll val)
    {
        while(pos <= n)
        {
            c[pos] += val;
            pos += lowbit(pos);
        }
    }
    
    lll getsum(int pos)
    {
        lll ans = 0;
        while(pos > 0)
        {
            ans += c[pos];
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    int main()
    {
        int t,i,j,q;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(i=1;i<=n;i++)
                scanf("%d",&a[i]),b[i] = a[i];
            scanf("%d",&q);
            for(i=1;i<=q;i++)
                scanf("%d%d",&Q[i].L,&Q[i].R),Q[i].ind = i;
            memset(c,0,sizeof(c));
            sort(b+1,b+n+1);
            sort(Q+1,Q+q+1,cmp);
            int ind = unique(b+1,b+n+1)-b-1;
            for(i=1;i<=ind;i++)
                mp[b[i]] = i;
            for(i=1;i<=n;i++)   //d[i]为a[i]离散化后的数
                d[i] = mp[a[i]];
            memset(pos,0,sizeof(pos));  //pos 存上次出现的位置
            j = 1;
            for(i=1;i<=n;i++)
            {
                if(pos[d[i]]) modify(pos[d[i]],-a[i]);
                modify(i,a[i]);
                pos[d[i]] = i;
                while(j <= q && Q[j].R == i)
                {
                    ans[Q[j].ind] = getsum(Q[j].R)-getsum(Q[j].L-1);
                    j++;
                }
                if(j > q)
                    break;
            }
            for(i=1;i<=q;i++)
                printf("%I64d
    ",ans[i]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    条件随机场(crf)及tensorflow代码实例
    Adam作者大革新, 联合Hinton等人推出全新优化方法Lookahead
    33.服务之间的调用之RPC、Restful深入理解
    RPC框架调用过程详解
    Spring 面试问题 TOP 50
    myBatis+Spring+SpringMVC框架面试题整理
    JavaSSM框架精选50道面试题
    maven build的常用生命周期
    玄武短信接口和移动MAS短信接口的API封装
    Java异步执行多个HTTP请求的例子(需要apache http类库)
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3970435.html
Copyright © 2011-2022 走看看