1. 程式人生 > >數顏色

數顏色

string swap 什麽 bool IT Go HA reg har

題意:

  n個數,m個操作。

  • 查詢區間[a,b]內不同數字數
  • 將某個數修改為c

  題解:

  帶修改莫隊。

與普通莫隊不同的就是要記錄一下每個查詢操作前有多少個修改操作,然後暴力修改或改回去。

題目鏈接:https://www.luogu.org/problemnew/show/P1903

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define
LL long long #define RI register int using namespace std; const int INF = 0x7ffffff ; const int S = 1e6 + 10 ; const int N = 10000 + 10 ; inline int read() { int k = 0 , f = 1 ; char c = getchar() ; for( ; !isdigit(c) ; c = getchar()) if(c == -) f = -1 ; for( ; isdigit(c) ; c = getchar()) k
= k*10 + c-0 ; return k*f ; } struct Que { int l, r, ti, id ; }q[N] ; int n, m, qcnt = 0, rcnt = 0, hh[N], pp[1010], cc[1010], res[N], pos[N], num[S], ans = 0 ; int L = 1, R = 0, T = 0 ; inline bool cmp1(Que s,Que t) { // 其實我也不知道怎麽排序最快qaq if(pos[s.l] == pos[t.l]) { if(pos[s.r] == pos[t.r]) return
s.ti < t.ti ; return s.r < t.r ; } return s.l < t.l ; } inline void add(int x) { if(!num[hh[x]]) ans ++ ; num[hh[x]] ++ ; } inline void del(int x) { num[hh[x]] -- ; if(!num[hh[x]]) ans -- ; } inline void addt(int t) { if(pp[t] >= L && pp[t] <= R) { num[hh[pp[t]]] -- ; if(!num[hh[pp[t]]]) ans -- ; if(!num[cc[t]]) ans ++ ; num[cc[t]] ++ ; } swap(hh[pp[t]],cc[t]) ; // 這是一步很神奇的操作 // 因為記錄每個位置的歷史值顯然是十分麻煩的。 // 我們可以觀察一個性質就是當一個修改操作被改回去時,就是原值變成修改值,修改值變成原值 // 所以只要交換一下即可 } int main() { n = read(), m = read() ; int base = sqrt(n) ; for(int i=1;i<=n;i++) hh[i] = read(), pos[i] = (i-1)/base + 1 ; char cs ; for(int i=1;i<=m;i++) { cin>>cs ; if(cs == Q) { q[++qcnt].l = read(), q[qcnt].r = read() ; q[qcnt].ti = rcnt ; q[qcnt].id = qcnt ; } else { pp[++rcnt] = read(), cc[rcnt] = read() ; } } sort(q+1,q+qcnt+1,cmp1) ; for(int i=1;i<=qcnt;i++) { while(L < q[i].l) del(L++) ; while(L > q[i].l) add(--L) ; while(R < q[i].r) add(++R) ; while(R > q[i].r) del(R--) ; // 以上與普通莫隊相同 while(T < q[i].ti) addt(++T) ; while(T > q[i].ti) addt(T--) ; // 為什麽都是add操作呢?看看addt函數就知道了qwq res[q[i].id] = ans ; } for(int i=1;i<=qcnt;i++) { printf("%d\n",res[i]) ; } return 0 ; }

PS:scanf讀單字符時不忽略空格與換行符T_T,換用cin即可.

數顏色