spoj DQUERY-D-query (the number of different numbers in the interval chair tree or BIT)

Topic link

Given a sequence containing n numbers, each time the number of different numbers in the interval [l, r] is asked.
You can use a chairperson tree or a tree-like array, all of which are based on the same principle. Swipe from left to right, and record the last occurrence of each number. When scanning to the position i, the position of
a[i] last appeared -1, and the position of i+1. Then answer all query intervals [x, i] (sum of BIT intervals). The chairman tree is also the same principle,
just to save the historical version.

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;
}
*/

Guess you like

Origin blog.csdn.net/KIJamesQi/article/details/52266655