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

Posted qieqiemin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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';
        
    



以上是关于HH的项链 HYSBZ - 1878 (莫队/ 树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-1878: [SDOI2009]HH的项链(莫队算法)

[BZOJ1878][SDOI2009]HH的项链 莫队

BZOJ 1878: [SDOI2009]HH的项链 | 莫队

[SDOI2009][bzoj1878] HH的项链 [莫队模板题]

BZOJ 1878:[SDOI2009]HH的项链(莫队算法)

bzoj1878 [SDOI2009]HH的项链莫队