思路:
用vector存一下各种颜色的区间,每次处理颜色的区间,相同颜色不需要更新。区间最多1e6个没错,但是随着颜色的更替区间只会越来越少。
维护区间左右两端的颜色,lazy一下。
区间合并的时候 sum= sum_left + sum_right , 如果左儿子的区间右边和右儿子的区间左边颜色相同 sum--。
复杂度:don't know;
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; struct Seg{ int Sum; int Lazy; int Left,Right; int Left_Color,Right_Color; }q[N*4]; struct asd{ int Left,Right; }; vector<asd>eg[1000000+10]; int col[N]; void Pushdown(int num) { if(q[num].Lazy==-1) return; q[num<<1].Lazy=q[num<<1|1].Lazy=q[num].Lazy; q[num<<1].Sum=q[num<<1|1].Sum=1; q[num<<1].Left_Color=q[num<<1].Right_Color=q[num].Lazy; q[num<<1|1].Left_Color=q[num<<1|1].Right_Color=q[num].Lazy; q[num].Lazy=-1; } void Build(int num,int Left,int Right) { q[num].Left=Left;q[num].Right=Right;q[num].Lazy=-1; if(Left == Right){ q[num].Sum=1; q[num].Left_Color=q[num].Right_Color=col[Left]; return; } int Mid=(Left+Right)>>1; Build(num<<1,Left,Mid); Build(num<<1|1,Mid+1,Right); q[num].Left_Color=q[num<<1].Left_Color; q[num].Right_Color=q[num<<1|1].Right_Color; if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum-1; else q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum; } int Query(int num,int Left,int Right) { if(q[num].Left>=Left && q[num].Right<=Right) return q[num].Sum; Pushdown(num); int Mid=(q[num].Left+q[num].Right)>>1; if(Mid>=Right) return Query(num<<1,Left,Right); else if(Mid<Left) return Query(num<<1|1,Left,Right); else{ int ans=0; ans+=Query(num<<1,Left,Mid); ans+=Query(num<<1|1,Mid+1,Right); if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) ans--; return ans; } } void Update(int num,int Left,int Right,int Color) { if(Left<=q[num].Left && q[num].Right<=Right){ q[num].Lazy=Color; q[num].Sum=1; q[num].Left_Color=q[num].Right_Color=Color; return; } Pushdown(num); int Mid=(q[num].Left+q[num].Right)>>1; if(Mid>=Right) Update(num<<1,Left,Right,Color); else if(Mid<Left) Update(num<<1|1,Left,Right,Color); else { Update(num<<1,Left,Mid,Color); Update(num<<1|1,Mid+1,Right,Color); } q[num].Left_Color=q[num<<1].Left_Color; q[num].Right_Color=q[num<<1|1].Right_Color; q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum; if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) q[num].Sum--; } void init(int n) { for(int i=0;i<=1000000;i++) eg[i].clear(); asd temp; int Color,Pre_Color=-1; for(int i=1;i<=n;i++) { scanf("%d",&Color); col[i]=Color; if(Pre_Color==-1){ temp.Left=i; Pre_Color=Color; } else if(Pre_Color!=Color){ temp.Right=i-1; eg[Pre_Color].push_back(temp); temp.Left=i; Pre_Color=Color; } } temp.Right=n; eg[Pre_Color].push_back(temp); Build(1,1,n); } void solve(int n) { asd temp; int Left,Right,x,y; int op; while(n--) { scanf("%d",&op); if(op==1) { scanf("%d%d",&x,&y); if(x==y) continue; int sz=eg[x].size(); for(int i=0;i<sz;i++) { temp=eg[x][i]; Update(1,temp.Left,temp.Right,y); eg[y].push_back(eg[x][i]); } eg[x].clear(); } else { scanf("%d%d",&Left,&Right); printf("%d ",Query(1,Left,Right)); } } } int main() { int n,T,Q; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&Q); init(n); solve(Q); } return 0; }