Luogu P1903 [國家集訓隊]數顏色 / 維護隊列___帶修莫隊

題目大意:

墨墨購買了一套N支彩色畫筆(其中有些顏色可能相同),擺成一排,你需要回答墨墨的提問。墨墨會向你發佈如下指令:
1、 Q L R代表詢問你從第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。
2、 R P Col 把第P支畫筆替換爲顏色Col。
在這裏插入圖片描述

分析:

沒有修改操作就是直接上莫隊即可
有了修改操作我們就引入一個時間戳,對於一個詢問,就記錄一下它前面有多少個修改
在莫隊過程中進行修改即可

代碼:

#include <bits/stdc++.h>

#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)

#define N 150005

using namespace std;

typedef long long ll;

struct Node {
    int l, r, id, cp;
}q1[N];
struct Code {
	int id, x;
}q2[N];
int beln[N], ans[N], cnt[N*7], a[N], n, m, now, tot1, tot2;

void read(int &x) {
	int f = 1; x = 0; char s = getchar();
	while (s < '0' || s > '9') { if (s == '-') f = - 1; s = getchar(); }
	while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
	x = x * f;
}

bool cmp(Node aa, Node bb) {
    return (beln[aa.l] == beln[bb.l]) ? ((beln[aa.r] == beln[bb.r] ? aa.cp < bb.cp : beln[aa.r] < beln[bb.r])) : beln[aa.l] < beln[bb.l];
}

void add(int x) {
    if (cnt[x] == 0) ++now; ++cnt[x];
}

void del(int x) {
    if (cnt[x] == 1) --now; --cnt[x];
}

void write(int x) {
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int main() {
    read(n); read(m);
    int siz = pow(n, 2.0 / 3.0);
    rep(i, 1, ceil((double)n / siz)) 
	    rep(j, (i - 1) * siz + 1, i * siz) beln[j] = i;
		         
    rep(i, 1, n) read(a[i]);
    char opt[5];
	rep(i, 1, m) {
	    scanf("%s", opt);
		if (opt[0] == 'Q') ++tot1, read(q1[tot1].l), read(q1[tot1].r), q1[tot1].id = tot1, q1[tot1].cp = tot2; 
		   else ++tot2, read(q2[tot2].id), read(q2[tot2].x);
	}
    sort(q1 + 1, q1 + tot1 + 1, cmp);
    int l = 1, r = 0, z = 0;
    rep(i, 1, tot1) {
        while (l < q1[i].l) del(a[l]), l++;
        while (l > q1[i].l) l--, add(a[l]);
        while (r < q1[i].r) r++, add(a[r]);
        while (r > q1[i].r) del(a[r]), r--;
        while (z < q1[i].cp) {
        	++z; 
			if (q1[i].l <= q2[z].id && q2[z].id <= q1[i].r) del(a[q2[z].id]), add(q2[z].x);
        	swap(a[q2[z].id], q2[z].x);
		}
		while (z > q1[i].cp) {
        	if (q1[i].l <= q2[z].id && q2[z].id <= q1[i].r) del(a[q2[z].id]), add(q2[z].x);
        	swap(a[q2[z].id], q2[z].x);	
			--z;	
		}
		ans[q1[i].id] = now;
    }
	rep(i, 1, tot1) write(ans[i]), printf("\n");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章