定义:将两个数据结构合并时,应将小的数据结构中的元素一个一个分别插入大的数据结构。
顺便写了一道“简单”题 —— 梦幻布丁 (可坑死我了是我太弱了)
现在回过头来这道题真的不难,我只是栽到以前挖的坑里去了(链表没学好)
这告诉我们一个道理 —— 千万不要边走边挖坑啊,有坑赶紧填!
我jio得这篇代码注释真的很良心(因为几乎没有人给这么简单的代码标注释)
好了...... 笔者叨叨叨正式结束
- 颜色一定是单调不增,段数一定是单调不增的,可以一边修改一边 ans--
-
用链表维护每一个颜色的下标,启发式合并,每次取出较小的,如果某个位置的前面或后面原来不同改颜色后相同
就 ans--
——摘自大米饼
1 #include<cstdio> 2 #include<iostream> 3 #define N 100010 4 #define M 1000010 5 using namespace std; 6 int n,m,ans; 7 int c[N],next[N],ft[M],head[M],s[M],st[M]; 8 //c[i]表示第i个数字的颜色 9 //ft[i]第i种颜色为 ft[i] 10 //head[i]第 i种颜色的表头,next[i]记下一个 11 //s[i]第 i种颜色的个数 12 //st[i]第 i种颜色的首位置 13 int read(){ 14 int x=0,f=1; char c=getchar(); 15 while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} 16 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 17 return x*f; 18 } 19 void solve(int a,int b){ 20 for(int i=head[a];i;i=next[i]){ //遍历每个颜色为 a的元素 21 if(c[i+1]==b) ans--; //更改后的颜色 与 右邻颜色相同 22 if(c[i-1]==b) ans--; //更改后的颜色 与 左邻颜色相同 23 } 24 for(int i=head[a];i;i=next[i]) c[i]=b; // 改变颜色 a->b head[a]==b 25 next[st[a]]=head[b]; head[b]=head[a]; // a(内部实际颜色已改变)合并到 b上 26 s[b]+=s[a]; //b颜色的个数 累加上 a(已改变为 b)的个数 27 head[a]=st[a]=s[a]=0; //有关 a 清零 28 } 29 int main() 30 { 31 n=read(),m=read(); 32 for(int i=1;i<=n;i++){ 33 c[i]=read(); 34 ft[c[i]]=c[i]; 35 if(c[i]!=c[i-1]) ans++; 36 if(!head[c[i]]) st[c[i]]=i; 37 s[c[i]]++; next[i]=head[c[i]]; head[c[i]]=i; 38 //这个赋值法就是这样,和邻接表一个道理(一直不太会,因为会打就一直咕着),一开始折磨死我了,还好没有放弃。 39 //我是带了一组简单的数据模拟了一遍(我太弱了),现在看多了就好多了 ,加油 ^_^ 40 } 41 for(int i=1;i<=m;i++){ 42 int a,b,x=read(); 43 if(x==2) printf("%d ",ans); 44 else{ 45 a=read(),b=read(); 46 if(a==b) continue; //改变为相同颜色=不变 47 if(s[ft[a]]>s[ft[b]]) swap(ft[a],ft[b]); //保证 小的(a)合并进大的(b) 48 a=ft[a],b=ft[b]; // ft[x] 用于维护实际颜色(x) 49 if(s[a]==0) continue; // 没有 a的颜色 50 solve(a,b); 51 } 52 } 53 return 0; 54 }