洛谷P1972(莫隊演算法)
題目連結:https://www.luogu.org/problemnew/show/P1972
題目描述
HH 有一串由各種漂亮的貝殼組成的項鍊。HH 相信不同的貝殼會帶來好運,所以每次散步完後,他都會隨意取出一段貝殼,思考它們所表達的含義。HH 不斷地收集新的貝殼,因此,他的項鍊變得越來越長。有一天,他突然提出了一個問題:某一段貝殼中,包含了多少種不同的貝殼?這個問題很難回答……因為項鍊實在是太長了。於是,他只好求助睿智的你,來解決這個問題。
輸入輸出格式
輸入格式:第一行:一個整數N,表示項鍊的長度。
第二行:N 個整數,表示依次表示項鍊中貝殼的編號(編號為0 到1000000 之間的整數)。
第三行:一個整數M,表示HH 詢問的個數。
接下來M 行:每行兩個整數,L 和R(1 ≤ L ≤ R ≤ N),表示詢問的區間。
輸出格式:M 行,每行一個整數,依次表示詢問對應的答案。
輸入輸出樣例
說明
資料範圍:
對於100%的資料,N <= 500000,M <= 200000。
思路:通過這道題學習了一種新的演算法,莫隊演算法。它在解決離線處理不可修改的區間時有很大優勢,複雜度n根號n,且常數比較小。但這道題後來資料加強了,得了80分,但莫隊仍是處理該類問題的有力武器(好寫。。。)。
上程式碼:
#include<bits/stdc++.h>
using namespace std;
typedef struct
{
int lb;
int rb;
int ind;
} node;
node q[200010];
int a[500010];
int pos[500010];
int ans[200010];
int sum=0;
bool cmp(node x,node y)
{
if(pos[x.lb]!=pos[y.lb])
return pos[x.lb]<pos[y.lb];
else
return pos[x.rb]<pos[y.rb];
}
int vis[1000010];
int main()
{
int n,m;
scanf("%d",&n);
int block=sqrt(n);
a[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
pos[i]=(i-1)/block+1;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].lb,&q[i].rb);
q[i].ind=i;
}
int l=0;
int r=0;
int sum=0;
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++)
{
while(l<q[i].lb)
{
vis[a[l]]--;
if(vis[a[l]]==0)
sum--;
l++;
}
while(l>q[i].lb)
{
l--;
vis[a[l]]++;
if(vis[a[l]]==1)
sum++;
}
while(r<q[i].rb)
{
r++;
vis[a[r]]++;
if(vis[a[r]]==1)
sum++;
}
while(r>q[i].rb)
{
vis[a[r]]--;
if(vis[a[r]]==0)
sum--;
r--;
}
ans[q[i].ind]=sum;
}
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
相關文章
- 洛谷P4074糖果公園(帶修莫隊)
- 洛谷P1494 [國家集訓隊]小Z的襪子(莫隊)
- 洛谷團隊
- 莫隊演算法演算法
- 洛谷P1223 排隊接水
- 基礎莫隊演算法演算法
- 【演算法學習】莫隊演算法
- 洛谷 P2257 YY的GCD(莫比烏斯反演)GC
- 洛谷P2062 分隊問題(dp)
- 莫隊
- 洛谷
- 莫隊演算法學習筆記演算法筆記
- dfs與貪心演算法——洛谷5194演算法
- 神奇的莫隊
- 莫隊詳解
- 分塊 and 莫隊
- 分塊與莫隊
- 根號分治莫隊
- 基礎莫隊模板
- 洛谷——玩具謎題
- 英雄聯盟(洛谷)
- 洛谷P1786
- 洛谷P6786
- 洛谷 - P5369
- 洛谷P10725
- 洛谷P10693
- 洛谷 - P6190
- 洛谷死亡時間
- 洛谷題單 演算法2-3 分治與倍增演算法
- 莫隊學習筆記筆記
- 洛谷八皇后問題
- 洛谷 P10254 口吃
- 洛谷傻逼之處
- 洛谷 P3958乳酪
- 昨天放洛谷的圖
- 將洛谷私信接入WindowsWindows
- 洛谷網校學習
- 【洛谷】【分支】月份天數