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的项链(莫队算法)
BZOJ 1878: [SDOI2009]HH的项链 | 莫队
[SDOI2009][bzoj1878] HH的项链 [莫队模板题]