P3201 [HNOI2009] 梦幻布丁——线段树合并 set启发式合并
[HNOI2009] 梦幻布丁
题目描述
\(n\) 个布丁摆成一行,进行 \(m\) 次操作。每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色。
例如,颜色分别为 \(1,2,2,1\) 的四个布丁一共有 \(3\) 段颜色.
输入格式
第一行是两个整数,分别表示布丁个数 \(n\) 和操作次数 \(m\)。
第二行有 \(n\) 个整数,第 \(i\) 个整数表示第 \(i\) 个布丁的颜色 \(a_i\)。
接下来 \(m\) 行,每行描述一次操作。每行首先有一个整数 \(op\) 表示操作类型:
- 若 \(op = 1\),则后有两个整数 \(x, y\),表示将颜色 \(x\) 的布丁全部变成颜色 \(y\)。
- 若 \(op = 2\),则表示一次询问。
输出格式
对于每次询问,输出一行一个整数表示答案。
样例 #1
样例输入 #1
4 3
1 2 2 1
2
1 2 1
2
样例输出 #1
3
1
提示
样例 1 解释
初始时布丁颜色依次为 \(1, 2, 2, 1\),三段颜色分别为 \([1, 1], [2, 3], [4, 4]\)。
一次操作后,布丁的颜色变为 \(1, 1, 1, 1\),只有 \([1, 4]\) 一段颜色。
数据规模与约定
对于全部的测试点,保证 \(1 \leq n, m \leq 10^5\),\(1 \leq a_i ,x, y \leq 10^6\)。
提示
请注意,不保证颜色的编号不大于 \(n\),也不保证 \(x \neq y\),\(m\) 不是颜色的编号上限。
分析
线段树合并模板,注意不要自己合并自己。
又:链表启发式合并
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100,M=1e6+100;
struct segtree
{
int lc,rc,val;
int lef,rig;
}s[N<<6];
struct col
{
int x,y,op;
}q[N];
int n,m,root[M],tot;
int h[M],ans;
void pushup(int i)
{
s[i].lef=(s[i].lc>0)?(s[s[i].lc].lef):(s[s[i].rc].lef);
s[i].rig=(s[i].rc>0)?(s[s[i].rc].rig):(s[s[i].lc].rig);
s[i].val=s[s[i].lc].val+s[s[i].rc].val-(s[s[i].rc].lef==s[s[i].lc].rig+1);
}
void upd(int &i,int l,int r,int x)
{
if(!i)i=++tot;
if(l==r)
{
s[i].lef=s[i].rig=l;
s[i].val=1;
return ;
}
int mid=(l+r)>>1;
if(x<=mid)
upd(s[i].lc,l,mid,x);
else
upd(s[i].rc,mid+1,r,x);
pushup(i);
}
void merg(int &i,int &j,int l,int r)
{
if(i==0 || j==0)
{
i+=j;
return ;
}
if(l==r)
{
s[i].val=1;
s[i].lef=s[i].rig=l;
return ;
}
int mid=(l+r)>>1;
merg(s[i].lc,s[j].lc,l,mid);
merg(s[i].rc,s[j].rc,mid+1,r);
pushup(i);
}
void init()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",h+i);
for(int i=1;i<=n;++i)
{
ans=ans-s[root[h[i]]].val;
upd(root[h[i]],1,n,i);
ans=ans+s[root[h[i]]].val;
}
}
void work()
{
while(m--)
{
int opt,x,y;
scanf("%d",&opt);
if(opt==1)
{
scanf("%d%d",&x,&y);
if(x==y)continue;
ans=ans-s[root[x]].val-s[root[y]].val;
merg(root[y],root[x],1,n);
root[x]=0;
ans+=s[root[y]].val;
}
else
printf("%d\n",ans);
}
}
int main()
{
init();
work();
return 0;
}
本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18576187