Turing Tree HDU - 3333

Turing Tree HDU - 3333

题意:

给你一个长度为n的数组, q次询问, 每次询问问区间\([l, r]\)不同元素之和是多少?

题解:

A: 这题用主席树咋写啊?

B:嗯嗯,这题其实用的是主席的思想而节约空间。如果这题不考虑空间问题, 我们可以建n颗普通线段树,且我们要保证第 \(i\) 颗线段树 中 a[i]只出现再第 \(i\) 个位置,且只出现一次(如果前面出现了就删点)。线段树维护区间和。

A: 如果考虑空间问题, 就可以想主席树一样,没个版本连接上一个版本。

B: 是的。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 30007;
typedef long long ll;

struct hjt{
    int l, r;
    ll sum;
}tree[40 * N];

int n, q, rt[N], top = 1;
ll a[N];

#define m  (l + r) / 2

void update(ll v, int pos,int last, int &now, int l, int r){
    now = top++;  
    tree[now] = tree[last];  
    if(l == r){ 
        tree[now].sum = v;
        return;
    } 
    if(pos <= m) update(v, pos, tree[last].l, tree[now].l, l, m);
    else update(v, pos, tree[last].r, tree[now].r, m + 1, r);
    tree[now].sum = tree[tree[now].l].sum + tree[tree[now].r].sum;
}

ll query(int now, int ql, int qr, int l, int r){
    if(ql <= l && qr >= r) return tree[now].sum;
    ll ans = 0; 
    if(ql <= m) ans += query(tree[now].l, ql, qr, l, m);
    if(qr > m) ans += query(tree[now].r, ql, qr, m + 1, r);
    return ans;
}

map<ll, int>vis;

int main(){
    int t; scanf("%d", &t);
    while(t--){ 
        memset(rt, 0, sizeof(rt)); 
        vis.clear();  
        top = 1;  
        memset(tree, 0, sizeof(tree));  scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
        } 
        for(int i = 1; i <= n; i++){
            if(vis[a[i]] == 0){
                update(a[i], i, rt[i - 1], rt[i], 1, n); 
                vis[a[i]] = i;
            }else{
                int temp; 
                update(0, vis[a[i]], rt[i - 1], temp, 1, n); 
                update(a[i], i, temp, rt[i], 1, n);
                vis[a[i]] = i;
            }
        }
        scanf("%d", &q);
        while(q--){  
            int l, r; 
            scanf("%d %d", &l, &r);  
            ll ans = query(rt[r], l, r, 1, n);
            printf("%lld\n", ans);
        }
    }
}
posted @ 2020-07-10 15:11  ccsu_zhaobo  阅读(51)  评论(0)    收藏  举报