数据结构(启发式合并):HNOI 2009 梦幻布丁

Description

N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.

Input

第 一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表 示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0

Output

针对第二类操作即询问,依次输出当前有多少段颜色.

Sample Input

4 3
1 2 2 1
2
1 2 1
2

Sample Output

3

1

  本地AC,BZOJ上RE,唉。

  水题,注意不要把set定义在结构体里,大数据会错,有个陷阱就是x==y。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <set>
 6 using namespace std;
 7 const int N=200010;
 8 set<int>::iterator it1,it2;
 9 int c[N],id[N*10],s[N];
10 int n,Q,ans,tot;set<int>v[N];
11 void Insert(int p,int i){
12     it2=v[p].lower_bound(i);
13     if(it2!=v[p].end()&&i+1==*it2)s[p]-=1;
14     if(it2!=v[p].begin()&&i-1==*(--it2))s[p]-=1;
15     v[p].insert(i);s[p]+=1;
16 }
17
18 int main(){
19     freopen("pudding.in","r",stdin);
20     freopen("pudding.out","w",stdout);
21     ios::sync_with_stdio(false);
22     cin.tie(NULL),cout.tie(NULL);
23     cin>>n>>Q;
24     for(int i=1;i<=n;i++)cin>>c[i];
25     for(int i=1;i<=n;i++){
26         int &p=id[c[i]];
27         if(!p)p=++tot;
28         Insert(p,i);
29     }
30
31     for(int i=1;i<=tot;i++)ans+=s[i];
32     int tp,x,y,px,py;
33     while(Q--){
34         cin>>tp;
35         if(tp==1){
36             cin>>x>>y;if(x==y)continue;
37             if(v[id[x]].size()>v[id[y]].size())swap(id[x],id[y]);
38             int px=id[x],py=id[y];ans-=s[px]+s[py];
39             for(it1=v[px].begin();it1!=v[px].end();it1++)
40                 Insert(py,*it1);
41             ans+=s[py];s[px]=0;v[px].clear();
42         }
43         if(tp==2)cout<<ans<<"\n";
44     }
45     return 0;
46 }
时间: 2024-12-28 21:36:47

数据结构(启发式合并):HNOI 2009 梦幻布丁的相关文章

BZOJ 1483 HNOI 2009 梦幻布丁 链表+启发式合并

题目大意:给出一串颜色,有两种操作,1.询问有多少块颜色.2.将一种颜色改变成另一种颜色. 思路:好像和染色什么的比较像,但是看了题解之后发现完全不是那么回事. 对于每一种颜色维护一个链表,然后在修改颜色的时候,暴力修改一种颜色成为另一种颜色,用启发式合并可以保证复杂度不超过O(nlogn).但是由于是启发式合并,有可能导致你就改了反了颜色,这个时候记录一个映射,然后把修改错的记录下来.各种信息仔细讨论一下... CODE: #include <cstdio> #include <cst

[BZOJ 1483][HNOI 2009]梦幻补丁(有序表启发式合并)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1483 分析: 先将不同的颜色的出现位置从小到大用几条链表串起来,然后统计一下答案 对于每次修改,修改一下答案即可,修改之后需要将两个颜色的链表合并就行了,但感觉似乎会TLE? 以下摘录与Hzwer的blog: 1:将两个队列合并,有若干队列,总长度为n,直接合并,最坏O(N), 2:启发式合并呢? 每次我们把短的合并到长的上面去,O(短的长度) 咋看之下没有多大区别, 下面让我们看看

数据结构 - 启发式合并

定义:将两个数据结构合并时,应将小的数据结构中的元素一个一个分别插入大的数据结构. 顺便写了一道“简单”题 ——梦幻布丁 (可坑死我了是我太弱了) 现在回过头来这道题真的不难,我只是栽到以前挖的坑里去了(链表没学好) 这告诉我们一个道理 —— 千万不要边走边挖坑啊,有坑赶紧填! 我jio得这篇代码注释真的很良心(因为几乎没有人给这么简单的代码标注释) 好了...... 笔者叨叨叨正式结束   颜色一定是单调不增,段数一定是单调不增的,可以一边修改一边 ans-- 用链表维护每一个颜色的下标,启发

【BZOJ1483】[HNOI2009]梦幻布丁 链表+启发式合并

[BZOJ1483][HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2

BZOJ 1483:[HNOI2009]梦幻布丁(链表+启发式合并)

[HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有

【BZOJ1483】【链表启发式合并】梦幻布丁

Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个

bzoj 1483: [HNOI2009]梦幻布丁 启发式合并vector

1483: [HNOI2009]梦幻布丁 Time Limit: 10 Sec  Memory Limit: 64 MB[Submit][Status][Discuss] Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操

【链表+启发式合并】Bzoj1483 [HNOI2009] 梦幻布丁

Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. Input 第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个

BZOJ 1483 HNOI2009 梦幻布丁 链表+启发式合并

题目大意:给定n个布丁,每个布丁有一个颜色,多次将某种颜色的所有布丁变为另一种颜色,多次询问颜色段数 数据范围:n<=10W 颜色数<=100W 链表的启发式合并0.0 一直没写明白 其实就是开个链表记录每种颜色的位置,合并时撸一遍短的链看看两边是不是长链的颜色就行 不过交换比较麻烦0.0 要开个数组记录每个数字代表的真实颜色 交换时把数组的这两个位置也交换下就可以了 注意用过的垃圾不要留在原位 size合并掉就清零 head合并走了就弄成NULL 不然会挂 强迫症的福音啊 #include&