zoukankan      html  css  js  c++  java
  • HDU 3333 Turing Tree 树状数组 离线查询

    题意: 给你一个数列,然后有n个查询,问你给定区间中不同数字的和是多少。

    思路还是比较难想的,起码对于我来说。

    将区间按照先右端点,后左端点从小到大排序之后,对于每个查询,我只要维护每个数字出现的最后一次就可以了(这个结论稍微想一下就可以证明是正确的)。

    然后就是简单的点更新,区间求和问题了~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <set>
    #include <vector>
    #include <string>
    #include <queue>
    #include <deque>
    #include <bitset>
    #include <list>
    #include <cstdlib>
    #include <climits>
    #include <cmath>
    #include <ctime>
    #include <algorithm>
    #include <stack>
    #include <sstream>
    #include <numeric>
    #include <fstream>
    #include <functional>
    
    using namespace std;
    
    #define MP make_pair
    #define PB push_back
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<int> VI;
    typedef pair<int,int> pii;
    const int INF = INT_MAX / 3;
    const double eps = 1e-8;
    const LL LINF = 1e17;
    const double DINF = 1e60;
    const int maxn = 3e4 + 10;
    
    struct Seg {
        int l,r,id;
        LL ans;
        Seg(int l,int r,int id): l(l),r(r),id(id) {}
    }; 
    
    int n,val[maxn],last[maxn],m;
    VI num;
    vector<Seg> query;
    LL C[maxn];
    bool ext[maxn];
    
    bool cmp(const Seg &a,const Seg &b) {
        if(a.r == b.r) return a.l < b.l;
        return a.r < b.r;
    }
    
    bool cmp1(const Seg &a,const Seg &b) {
        return a.id < b.id;
    }
    
    inline int lowbit(int x) {
        return x & (-x);
    }
    
    void addv(int pos,LL v) {
        while(pos <= n) {
            C[pos] += v; pos += lowbit(pos);
        }
    }
    
    LL ask_(int pos) {
        LL ret = 0;
        while(pos > 0) {
            ret += C[pos]; pos -= lowbit(pos);
        }
        return ret;
    }
    
    LL ask(int l,int r) {
        return ask_(r) - ask_(l - 1);
    }
    
    int getID(int Val) {
        return lower_bound(num.begin(),num.end(),Val) - num.begin() + 1;
    }
    
    void solve() {
        memset(C,0,sizeof(C));
        memset(last,-1,sizeof(last));
        int npos = 1;
        for(int i = 0;i < m;i++) {
            Seg &now = query[i];
            while(npos <= now.r) {
                int nowval = getID(val[npos]);
                if(last[nowval] != -1) addv(last[nowval],-val[npos]);
                last[nowval] = npos;
                addv(npos,val[npos]);
                npos++;
            }
            now.ans = ask(now.l,now.r);
        }
    }
    
    int main() {
        int T; scanf("%d",&T);
        while(T--) {
            query.clear();
            num.clear();
            int tmp; scanf("%d",&n);
            for(int i = 1;i <= n;i++) {
                scanf("%d",&val[i]); num.PB(val[i]);
            }
            sort(num.begin(),num.end());
            num.erase(unique(num.begin(),num.end()),num.end());
            scanf("%d",&m);
            for(int i = 0;i < m;i++) {
                int l,r; scanf("%d%d",&l,&r);
                query.PB(Seg(l,r,i));
            }
            sort(query.begin(),query.end(),cmp);
            solve();
            sort(query.begin(),query.end(),cmp1);
            for(int i = 0;i < m;i++) cout << query[i].ans << endl;
        }
        return 0;
    }
    

      

  • 相关阅读:
    redhat yum替换成CentOS yum 并修改源
    C++11新特性实验
    常见的安装包制作程序installer
    如何在数据库中删除并添加唯一索引?
    springboot中的restTemplate工具类
    如何使用swagger(一)
    The POM for com.qingmu:entity:jar:1.0.0-SNAPSHOT is missing, no dependency information available
    java.lang.IllegalStateException: Found multiple @SpringBootConfiguration annotated classes
    在使用postman中配置返回html页面
    Springboot中设置返回数据的时间格式
  • 原文地址:https://www.cnblogs.com/rolight/p/3925437.html
Copyright © 2011-2022 走看看