1. 程式人生 > >HDOJ3333 Turing Tree ---- 樹狀陣列離線查詢

HDOJ3333 Turing Tree ---- 樹狀陣列離線查詢

Problem Description

After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick thing happens again... Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.

Input

The first line is an integer T (1 ≤ T ≤ 10), indecating the number of testcases below. For each case, the input format will be like this: * Line 1: N (1 ≤ N ≤ 30,000). * Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000). * Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries. * Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).

Output

For each Query, print the sum of distinct values of the specified subsequence in one line.

Sample Input

2 3 1 1 4 2 1 2 2 3 5 1 1 2 1 3 3 1 5 2 4 3 5

Sample Output

1 5 6 3 6

 題意: 輸入n個數,給定m組詢問l,r,要求查詢出l-r區間內去重後的數字和(從1開始數)

 題解: 本來是想簡單複習下樹狀陣列,切個水題的,本來以為這題很簡單,結果寫出來一直TLE,一查才發現這題比我想象的難,思路的話就完全參照的

https://www.cnblogs.com/CSU3901130321/p/4754259.html ,因為不會這道題,程式碼基本照著他敲的。。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define MAXN 30010
using namespace std;
typedef long long ll;
ll c[MAXN]; // 儲存樹狀陣列
int input[MAXN]; // 輸入陣列
ll result[100010]; // 儲存查詢結果
map<int,int> mp;
struct Query {
    int l,r,id;
    void init(int a,int b,int c) {l = a, r = b,id = c;}
    bool operator < (const Query & q) const{
        return (r<q.r) || (r==q.r&&l<q.l);
    }
}qu[100010];
int n,m; // 輸入數的個數
int lowbit(int x) {return x & -x;}
// pos下標處增加x
void update(int pos,int x) {
    while(pos <= n) {
        c[pos] += x;
        pos = pos + lowbit(pos);
    }
}
// 查詢前x項和
ll query(int x) {
    ll cnt = 0;
    while(x >= 1) {
        cnt += (ll)c[x];
        x -= lowbit(x);
    }
    return cnt;
}


int main()
{
    int t;
    scanf("%d",&t);
    while(t--) {
        memset(c,0,sizeof(c));
        memset(qu,0,sizeof(qu));
        mp.clear();
        scanf("%d",&n);
        for(int i = 1;i <= n;i++) {
            scanf("%d",&input[i]);
        }
        scanf("%d",&m);
        int l,r;
        for(int i = 0;i < m;i++) {
            scanf("%d%d",&l,&r);
            qu[i].init(l,r,i);
        }
        sort(qu,qu+m);
        int cur = 0;// 當前要查詢的語句編號
        for(int i = 1;i <= n;i++) {
            if(mp.count(input[i]) == 0) {
                update(i,input[i]);
                mp.insert(make_pair(input[i],i));
            } else {
                update(mp[input[i]],-input[i]);
                update(i,input[i]);
                mp[input[i]] = i;
            }
            // 離線查詢
            while(qu[cur].r == i) {
                result[qu[cur].id] = query(qu[cur].r) - query(qu[cur].l-1);
                cur++;
            }
        }
        for(int i = 0;i < m;i++) {
            printf("%lld\n",result[i]);
        }
    }
    
    return 0;
}