spoj DQUERY - D-query(區間不同數的個數 主席樹 or BIT)

題目鏈接

給出含有n個數字的序列,每次問區間[l,r]不同數的個數。
可以用主席樹也可以用樹狀數組,做法都是同一個原理。從左往右掃一遍,記錄每個數上一次出現的位置。當掃到i位置時,
把a[i]上一次出現的位置-1,i這個位置+1。然後對於所有詢問區間[x, i]進行回答(BIT區間求和)。主席樹也是這個原理,
只是要保存歷史版本。

const int maxn = 3e4 + 123;
int ls[maxn*20], rs[maxn*20], root[maxn];
int sum[maxn*20];
int tot;
void build(int& rt, int l, int r) {
    rt = ++ tot;
    sum[rt] = 0;
    if (l == r) return ;
    int m = (l + r) >> 1;
    build(ls[rt], l, m);
    build(rs[rt], m + 1, r);
}
void updata(int last, int& rt, int l, int r, int pos, int val) {
    rt = ++ tot;
    sum[rt] = sum[last] + val;
    ls[rt] = ls[last];
    rs[rt] = rs[last];
    if (l == r) {
        // sum[rt] = val;
        return ;
    }
    int m = (l + r) >> 1;
    if (pos <= m) updata(ls[last], ls[rt], l, m, pos, val);
    else updata(rs[last], rs[rt], m + 1, r, pos, val);
    // sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}
int find(int rt,int l, int r, int pos) {
    int res = 0;
    if (l == r) return sum[rt];
    int m = (l + r) >> 1;
    if (pos <= m) return find(ls[rt], l, m, pos);
    return sum[ls[rt]] + find(rs[rt], m + 1, r, pos);
}
int a[maxn];
int main(int argc, const char * argv[])
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // ios::sync_with_stdio(false);
    // cout.sync_with_stdio(false);
    // cin.sync_with_stdio(false);

    int n;
    while(~scanf("%d", &n)) {
        tot = 0;
        for (int i = 1;i <= n;++i) {
            scanf("%d", &a[i]);
        }
        build(root[n + 1], 1, n);
        map<int, int> mp;
        for (int i = n;i >= 1;--i) {
            if (mp.find(a[i]) == mp.end()) {
                updata(root[i + 1], root[i], 1, n, i, 1);
            }else {
                int temp;
                updata(root[i + 1], temp, 1, n, mp[a[i]], -1);//隔開中間這個歷史版本
                updata(temp, root[i], 1, n, i, 1);
            }
            mp[a[i]] = i;
        }
        int q;scanf("%d", &q);
        while(q--) {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d\n", find(root[l], 1, n, r));
        }
    }

    // showtime;
    return 0;
}
/*
const int maxn = 1e6 + 10;
struct BIT {
    int sum[maxn];
    void init() {
        memset(sum, 0, sizeof sum);
    }
    void add(int p, int v) {
        while(p < maxn) {
            sum[p] += v;
            p += lowbit(p);
        }
    }
    int find(int p) {
        int res = 0;
        while(p > 0) {
            res += sum[p];
            p -= lowbit(p);
        }
        return res;
    }
}solve;
map<int, int> last;
vector<vector<ii> > vec; 
int a[maxn];
int n, m;
int ans[maxn];
int main(int argc, const char * argv[])
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // ios::sync_with_stdio(false);
    // cout.sync_with_stdio(false);
    // cin.sync_with_stdio(false);

    while(~scanf("%d", &n)) {
        solve.init();
        last.clear();
        vec.clear();
        vec.resize(maxn);
        for (int i = 1;i <= n;++i) {
            scanf("%d", &a[i]);
        }
        scanf("%d", &m);
        for (int i = 1;i <= m;++i) {
            int l, r;
            scanf("%d%d", &l, &r);
            vec[r].push_back(ii(l, i));
        }
        for (int i = 1;i <= n;++i) {
            if (last[a[i]]) solve.add(last[a[i]], -1);
            last[a[i]] = i;
            solve.add(i, 1);
            for (auto x : vec[i]) {
                int idx = x.second;
                int l = x.first;
                ans[idx] = solve.find(i) - solve.find(l - 1);
                // debug(idx);
            }
        }
        for (int i = 1;i <= m;++i)
            printf("%d\n", ans[i]);
    }

    // showtime;
    return 0;
}
*/

/*
const int maxn =3e4 + 123;
int sum[maxn*20], ls[maxn*20], rs[maxn*20], root[maxn];
int a[maxn];
int tot;
int n;
void build(int& rt,int l, int r) {
    rt = ++tot;
    sum[rt] = 0;
    if (l == r) return ;
    int m = (l + r) >> 1;
    build(ls[rt], l, m);
    build(rs[rt], m + 1, r);
}
void updata(int last, int& rt,int l, int r, int pos, int val) {
    rt = ++tot;
    //從上一個線斷樹版本中複製數據
    sum[rt] = sum[last] + val;
    ls[rt] = ls[last];
    rs[rt] = rs[last];
    if (l == r) return ;
    int m = (l + r) >> 1;
    if (pos <= m) updata(ls[last], ls[rt], l, m, pos, val);
    else updata(rs[last], rs[rt], m + 1, r, pos, val);
}
int find(int pos, int rt, int l, int r) {
    if (l == r) return sum[rt];
    int m = (l + r) >> 1;
    if (pos <= m) return find(pos, ls[rt], l, m) + sum[rs[rt]];
    return find(pos, rs[rt], m + 1, r);
}

int main(int argc, const char * argv[])
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    // ios::sync_with_stdio(false);
    // cout.sync_with_stdio(false);
    // cin.sync_with_stdio(false);

    while(~scanf("%d", &n)) {
        for (int i = 1;i <= n;++i)
            scanf("%d", &a[i]);
        map<int, int> mp;
        build(root[0], 1, n);
        for (int i = 1;i <= n;++i) {
            if (mp.find(a[i]) == mp.end()) {
                updata(root[i - 1], root[i], 1, n, i, 1);
            }else {
                int temp;
                updata(root[i - 1], temp, 1, n, mp[a[i]], -1);
                updata(temp, root[i], 1, n, i, 1);
            }
            mp[a[i]] = i;
        }
        int q;scanf("%d", &q);
        while(q--) {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d\n", find(l, root[r], 1, n));
        }
    }

    // showtime;
    return 0;
}
*/
發佈了304 篇原創文章 · 獲贊 7 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章