HH的项链 HYSBZ - 1878 (莫队/ 树状数组)

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一

段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此他的项链变得越来越长。有一天,他突然提出了一

个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只

好求助睿智的你,来解决这个问题。

Input

第一行:一个整数N,表示项链的长度。

第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。

第三行:一个整数M,表示HH询问的个数。

接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

N ≤ 50000,M ≤ 200000。

Output

M行,每行一个整数,依次表示询问对应的答案。

Sample Input

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

Sample Output

2 2 4

Hint

思路:

1、用莫队的话就是一个模板题。

2、 用离线树状数组的话,将询问区间按照L升序排序,然后对数组中,每一个数a[i] 记录一个 Next [i] 代表这个数右边再一次出现的下标。

然后维护一个当前下标L =1 开始,更新树状数组即可。

莫队的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
ll ans[maxn];
ll Ans = 0ll;
int l = 0;
int r = 0;
int b[maxn];
int vis[maxn];
struct node {
    int l, r, id;
} a[maxn];
int pos[maxn];
int n, m;
int len;
bool cmp(node aa, node bb)
{
    if (pos[aa.l] == pos[bb.l]) {
        return aa.r < bb.r;
    } else {
        return pos[aa.l] < pos[bb.l];
    }
}
void add(int x)
{
    if (!vis[x]) {
        Ans++;
    }
    vis[x]++;
}
void del(int x)
{
    if (vis[x] == 1) {
        Ans--;
    }
    vis[x]--;
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    gg(n);
    len = (int)(sqrt(n));
    repd(i, 1, n) {
        gg(b[i]);
    }
    gg(m);
    repd(i, 1, m) {
        gg(a[i].l);
        gg(a[i].r);
        a[i].id = i;
        pos[i] = i / len;
    }
    sort(a + 1, a + 1 + m, cmp);
    repd(i, 1, m) {
        while (l > a[i].l) {
            l--;
            add(b[l]);
        }
        while (r < a[i].r) {
            r++;
            add(b[r]);
        }
        while (l < a[i].l) {
            del(b[l]);
            l++;
        }
        while (r > a[i].r) {
            del(b[r]);
            r--;
        }
        ans[a[i].id] = Ans;
    }
    repd(i, 1, m) {
        printf("%lld\n", ans[i]);
    }
    return 0;
}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}



树桩数组的代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int tree[maxn];
int lowbit(int x)
{
    return -x & x;
}
int n, m;
void add(int x, int val)
{
    while (x <= n) {
        tree[x] += val;
        x += lowbit(x);
    }
}
int ask(int x)
{
    int res = 0;
    while (x) {
        res += tree[x];
        x -= lowbit(x);
    }
    return res;
}
struct node {
    int l, r, ans, id;
} b[maxn];
bool cmp1(node aa, node bb)
{
    if (aa.l != bb.l) {
        return aa.l < bb.l;
    } else {
        return aa.l < bb.l;
    }
}
bool cmp2(node aa, node bb)
{
    return aa.id < bb.id;
}
int a[maxn];
int mx = -1;
int Next[maxn];
int pos[maxn];
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    gbtb;
    cin >> n;
    repd(i, 1, n) {
        cin >> a[i];
    }
    for (int i = n; i >= 1; i--) {
        Next[i] = pos[a[i]];
        pos[a[i]] = i;
        mx = max(mx, a[i]);
    }
    for (int i = 0; i <= mx; ++i) {
        if (pos[i]) {
            add(pos[i], 1);
        }
    }
    cin >> m;
    repd(i, 1, m) {
        cin >> b[i].l >> b[i].r;
        b[i].id = i;
    }
    sort(b + 1, b + 1 + m, cmp1);
    int l = 1;
    repd(i, 1, m) {
        while (l < b[i].l) {
            if (Next[l]) {
                add(Next[l], 1);
                // add(l, -1);可有可无。
            }
            l++;
        }
        b[i].ans = ask(b[i].r) - ask(b[i].l - 1);
    }
    sort(b + 1, b + 1 + m, cmp2);
    repd(i, 1, m) {
        printf("%d\n", b[i].ans );
    }
    return 0;

}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}



posted @ 2019-09-13 14:48  茄子Min  阅读(211)  评论(0编辑  收藏  举报