【國家集訓隊】 數顏色 - 莫隊
阿新 • • 發佈:2018-03-25
for pri nbsp tar esp div str oid int
題目描述
墨墨購買了一套N支彩色畫筆(其中有些顏色可能相同),擺成一排,你需要回答墨墨的提問。墨墨會向你發布如下指令:
1、 Q L R代表詢問你從第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。
2、 R P Col 把第P支畫筆替換為顏色Col。
為了滿足墨墨的要求,你知道你需要幹什麽了嗎?
輸入輸出格式
輸入格式:
第1行兩個整數N,M,分別代表初始畫筆的數量以及墨墨會做的事情的個數。
第2行N個整數,分別代表初始畫筆排中第i支畫筆的顏色。
第3行到第2+M行,每行分別代表墨墨會做的一件事情,格式見題幹部分。
輸出格式:
對於每一個Query的詢問,你需要在對應的行中給出一個數字,代表第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。
思路
帶修改莫隊模板題
莫隊算法詳見『這裏』
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
int n,m,now,block,cnt[maxn],a[maxn],ans[maxn];
struct Query {
int l,r,num;
inline bool operator < (Query cmp) const {
if (l/block != cmp.l/block) return l/block < cmp.l/block;
return r < cmp.r;
}
}q[maxn];
inline void add(int x) {
if (x > n+1) return;
cnt[x]++;
if (now == x && cnt[x] > 0)
for (int i = x;i <= n+1;i++)
if (!cnt[i]) {
now = i;
break;
}
}
inline void del(int x) {
if (x > n+1) return;
cnt[x]--;
if (!cnt[x]) now = min(now,x);
}
int main() {
scanf("%d%d",&n,&m);
block = sqrt(n);
a[0] = n+2;
for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
for (int i = 1;i <= m;i++) {
scanf("%d%d",&q[i].l,&q[i].r);
q[i].num = i;
}
sort(q+1,q+m+1);
int l = 0,r = 0;
for (int i = 1;i <= m;i++) {
while (l < q[i].l) del(a[l++]);
while (l > q[i].l) add(a[--l]);
while (r < q[i].r) add(a[++r]);
while (r > q[i].r) del(a[r--]);
ans[q[i].num] = now;
}
for (int i = 1;i <= m;i++) printf("%d\n",ans[i]);
return 0;
}
【國家集訓隊】 數顏色 - 莫隊