【BZOJ 2453】 维护队列
【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=2453
【算法】
带修改的莫队算法
当块的大小为N^(2/3)时,时间复杂度为 : O(n^(5/3))
但本题,当块的大小为sqrt(N)时,能够达到更优的复杂度
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 10010 const int MAXC = 1e6 + 5; int i,len,x,y,sum,l,r,n,now,qnum,m,cnt; int a[MAXN],block[MAXN],s[MAXC],ans[MAXN]; char op[5]; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } struct info { int x,y,last; } c[MAXN]; struct Query { int x,y,id,cur; } q[MAXN]; inline bool cmp(Query a,Query b) { if (block[a.x] == block[b.x]) { if (block[a.y] == block[b.y]) return a.cur < b.cur; else return block[a.y] < block[b.y]; } else return block[a.x] < block[b.x]; } inline void add(int x) { s[a[x]]++; if (s[a[x]] == 1) sum++; } inline void dec(int x) { s[a[x]]--; if (s[a[x]] == 0) sum--; } inline void worka(int now) { int x = c[now].x,y = c[now].y; if (x >= l && x <= r) dec(x); c[now].last = a[x]; a[x] = y; if (x >= l && x <= r) add(x); } inline void workb(int now) { int x = c[now].x,y = c[now].y; if (x >= l && x <= r) dec(x); a[x] = c[now].last; if (x >= l && x <= r) add(x); } int main() { read(n); read(m); len = sqrt(n); for (i = 1; i <= n; i++) block[i] = (i - 1) / len + 1; for (i = 1; i <= n; i++) read(a[i]); for (i = 1; i <= m; i++) { scanf("%s",&op); read(x); read(y); if (op[0] == 'Q') q[++qnum] = (Query){x,y,qnum,cnt}; else c[++cnt] = (info){x,y,0}; } sort(q+1,q+qnum+1,cmp); l = 1; r = 0; now = 0; sum = 0; for (i = 1; i <= qnum; i++) { for (; r < q[i].y; r++) add(r+1); for (; r > q[i].y; r--) dec(r); for (; l < q[i].x; l++) dec(l); for (; l > q[i].x; l--) add(l-1); for (now; now < q[i].cur; now++) worka(now+1); for (now; now > q[i].cur; now--) workb(now); ans[q[i].id] = sum; } for (i = 1; i <= qnum; i++) printf("%d\n",ans[i]); return 0; }