支持修改的莫队
-
对于每一个询问,记录以下内容:
- ( ext{Left,Right}):左右边界
- ( ext{Mapping}):时间轴,即在这个询问之前已经完成了前( ext{Mapping})个修改
-
按照( ext{Left})为第一关键字,( ext{Right})为第二关键字,( ext{Mapping})为第三关键字对询问排序。
-
莫队状态的转移:
- 在相同时间里,和普通莫队没有差异。
- 在不同时间里,如果询问的时间较早需要逐个消除操作的影响。如果询问的时间晚,需要逐个进行操作。
-
常数优化
- ( ext{main})函数里的局部变量要快于全局变量。
- 使用读入/输出优化。
-
Code
-
/* --- Hope in Hand --- */ #include <stdio.h> #include <string.h> #include <algorithm> #define GC getchar() #define Clean(X,K) memset(X,K,sizeof(X)) int Qread () { int X = 0 ; char C = GC ; while (C > '9' || C < '0') C = GC ; while (C >='0' && C <='9') { X = X * 10 + C - '0' ; C = GC ; } return X ; } const int Maxn = 50005 , U = 1000005; int A[Maxn] ,Ans[Maxn] , Vis[U]; struct Node { int X , Y , TIME , Mapping , Place , Raw_Value; }; Node Ask [Maxn] , Add[Maxn] ; bool Cmp (const Node &A , const Node &B) { if (A.X != B.X )return A.X < B.X ; if (A.Y != B.Y ) return (A.X &1 ? A.Y < B.Y : A.Y > B.Y ) ; return (A.Y & 1 ? A.TIME < B.TIME : A.TIME > B.TIME ) ; } void Write(int X) { if( X > 9 ) Write(X / 10); putchar(X % 10+ '0'); } int main () { int L = 0 , R = 0 , Time = 0 , Now = 0 , N ,M , Cq = 0 , Cr = 0 ; N = Qread () , M = Qread (); for (int i = 1 ; i <= N; ++ i) A[i] = Qread () ; for (int i = 1 ; i <= M; ++ i) { char C = GC ; while (C != 'Q' && C != 'R') C = GC ; if (C == 'Q') { Ask[++ Cq].X = Qread () ; Ask[Cq].Y = Qread () ; Ask[Cq].TIME = i ; Ask[Cq].Mapping = Cr ; Ask[Cq].Place = Cq ; } else { Add[++Cr].X = Qread () ; Add[Cr].Y = Qread () ; Add[Cr].TIME = i ; Add[Cr].Mapping = Cq ; } } Clean (Vis , 0) ; L = R = 1 , Vis[A[L]] = 1 , Now = 1 ; std :: sort (Ask + 1 , Ask + 1 + Cq , Cmp) ; for (int i = 1 ; i <= Cq ; ++ i) { while (L < Ask[i].X ) { -- Vis[A[L]] ; if (!Vis[A[L]]) -- Now ; ++ L ; } while (R < Ask[i].Y ) { ++ R ; ++ Vis[A[R]] ; if (Vis[A[R]] == 1) ++ Now ; } while (R > Ask[i].Y ) { -- Vis[A[R]] ; if (!Vis[A[R]]) -- Now ; -- R ; } while (Time < Ask[i].Mapping ) { ++ Time ; if (Add[Time].X >= L && Add[Time].X <= R) { --Vis[A[Add[Time].X ]] ; if (Vis[A[Add[Time].X ]] == 0) --Now ; ++Vis[Add[Time].Y ] ; if (Vis[Add[Time].Y ]== 1) ++Now ; } Add[Time].Raw_Value = A[Add[Time].X ] ; A[Add[Time].X ] = Add[Time].Y ; } while (Time > Ask[i].Mapping ) { if (Add[Time].X >= L && Add[Time].X <= R) { Vis[Add[Time].Y ] -- ; if (Vis[Add[Time].Y ] == 0) --Now ; ++Vis[Add[Time].Raw_Value ] ; if (Vis[Add[Time].Raw_Value ]== 1) ++Now ; } A[Add[Time].X ] = Add[Time].Raw_Value ; --Time ; } Ans[Ask[i].Place ] = Now ; } for (int i = 1 ; i <= Cq; ++ i)Write (Ans[i]) , putchar(10); fclose (stdin) , fclose (stdout) ; return 0 ; }
-
Thanks!