题意:给你一段数字,要你完成两个操作
1.把所有数字x换成数字y
2.输出[l,r]中有几段不同的数字
题解:
这题可以采用启发式合并,也就是每次把个数少的往个数大的上面合并,这样如果要合并成n个一样的最坏的情况是nlogn的(n/2*logn)
然后合并的时候用线段树单点更新下就行
时间复杂度O(nlog2n)
注意:
可能会让你合并颜色没有的节点,所以在改变合并方向的标记的时候两边都要标记一下
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define PB push_back
#define MP make_pair
#define ll long long
#define MS(a,b) memset(a,b,sizeof(a))
#define LL (rt<<1)
#define RR (rt<<1|1)
#define lson l,mid,LL
#define rson mid+1,r,RR
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lb(x) (x&(-x))
void In(){freopen("in.in","r",stdin);}
void Out(){freopen("out.out","w",stdout);}
const int N=1e5+10;
const int M=1e6+10;
const int Mbit=1e6+10;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
vector<int>v[M];
int mp[M];
struct node
{
int l,r,sum;
}tree[N<<2],ans;
void up(int rt)
{
tree[rt].l=tree[LL].l;tree[rt].r=tree[RR].r;
tree[rt].sum=tree[LL].sum+tree[RR].sum;
if(tree[LL].r==tree[RR].l)tree[rt].sum--;
}
void build(int l,int r,int rt)
{
if(l==r){
int x;scanf("%d",&x);
v[x].PB(l);
tree[rt].l=tree[rt].r=x;
tree[rt].sum=1;
return;
}
int mid=l+r>>1;
build(lson);
build(rson);
up(rt);
}
void update(int l,int r,int rt,int p,int col)
{
if(l==r){
tree[rt].l=tree[rt].r=col;
return;
}
int mid=l+r>>1;
if(p<=mid)update(lson,p,col);
else update(rson,p,col);
up(rt);
}
node query(int l,int r,int rt,int L,int R)
{
if(L<=l&&r<=R)return tree[rt];
node t1,t2;
int mid=l+r>>1;
if(L<=mid)t1=query(lson,L,R);
if(R>mid)t2=query(rson,L,R);
if(L<=mid&&R>mid){
t1.sum+=t2.sum;
if(t1.r==t2.l)t1.sum--;
t1.r=t2.r;
return t1;
}
else if(R<=mid)return t1;
else return t2;
}
int main()
{//In();
int T,kase=0,q,n,op,x,y,a,b;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
for(int i=1;i<M;i++)mp[i]=i,v[i].clear();
build(1,n,1);
while(q--){
scanf("%d%d%d",&op,&x,&y);
if(op==1){
if(x==y)continue;
a=mp[x];b=mp[y];
if(v[a].size()<=v[b].size()){
for(int i=0;i<v[a].size();i++){
int k=v[a][i];
v[b].PB(k);
update(1,n,1,k,b);
}
v[a].clear();
}
else{
mp[x]=b;mp[y]=a;
for(int i=0;i<v[b].size();i++){
int k=v[b][i];
v[a].PB(k);
update(1,n,1,k,a);
}
v[b].clear();
}
}
else{
printf("%d\n",query(1,n,1,x,y).sum);
}
}
}
return 0;
}