【BZOJ1483】【HNOI2009】梦幻布丁
题意
N 个布丁摆成一行,进行M次操作.
每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.
例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.
题解
注意可能出现把a改成b后再改回来的情况
首先一个最简单的暴力就是每个颜色用一个vector保存位置,修改时把所有要修改的布丁暴力插入到目标颜色的vector里。
然后注意到可以用启发式优化,修改时把小的插到大的里。
可以开一个数组$dic$记录每个颜色的真实颜色,初始时$dic[i]=i$
如果目标颜色比修改颜色小,那么就$swap(dic[a],dic[b])$
修改前先$a=dic[a],b=dic[b]$
代码
#include#include #include #include using namespace std; #define N 1000001 #define now q[a][i] int fa[N],col[N],dic[N]; bool vis[N]; vector q[N]; int main() { int n,m,cnt; cin>>n>>m; cnt=n; for(int i=1;i<=n;i++) { scanf("%d",&col[i]); q[col[i]].push_back(i); if(col[i]==col[i-1]) cnt--; } for(int i=1;i q[dic[b]].size()); if(flag) swap(dic[a],dic[b]); a=dic[a],b=dic[b]; for(int i=0;i