有n个独立的磁铁(1,2,⋯n标号)放在桌上,一个人对这n堆进行移动操作,然后另一个人询问。
有以下规则:
M X Y : 将含有编号X的磁铁块放在包含Y的磁铁块的顶端。(磁铁块指很多磁铁吸在了一起)
C X : 询问在编号X磁铁下的磁铁的数目。
Input Format
第1行一个整数,操作数p。
第2行到第p+1行:每一行是个合法操作,形如M X Y或C X。
Output Format
对于每个C操作输出一行,即对应的磁铁数。
Sample Input
6
M 1 6
C 1
M 2 4
M 2 6
C 3
C 4
Sample Output
1
0
2
About Test Data
对于全部数据:1≤n≤30000;1≤p≤100000
对于50%的数据: 1≤n≤1000;1≤p≤10000
就是这样一道题目,请问该怎么做呢?并查集?
十分感谢大家!
7 个解决方案
#1
方法一:数据分为两部分,磁铁数组和磁铁组表。
磁铁数组包含所有磁铁信息,磁铁信息中有磁铁组号(或指针)、该铁在组中的位置(就是其下有多少磁铁。
磁铁组是个线性表,元素是磁铁号,只要求遍历、添加、合并功能,用链表实现。
初始化:所有磁铁,位置为0;为所有磁铁创建单元磁铁组表。
M命令:找到X所在磁铁组GX、,O(1)操作;
找到Y所在磁铁组GY,O(1)操作;
遍历GX中的元素,将对应磁铁信息中的磁铁组号(或指针)改为GY,位置加上Length(GY),O(N)操作
GY合并到GX中,O(1)操作。
C命令:输出X中的位置信息
初始化时可以不创建磁铁组表,这样就要在M命令中进行判断,分别对GX和GY为空时进行处理
磁铁数组包含所有磁铁信息,磁铁信息中有磁铁组号(或指针)、该铁在组中的位置(就是其下有多少磁铁。
磁铁组是个线性表,元素是磁铁号,只要求遍历、添加、合并功能,用链表实现。
初始化:所有磁铁,位置为0;为所有磁铁创建单元磁铁组表。
M命令:找到X所在磁铁组GX、,O(1)操作;
找到Y所在磁铁组GY,O(1)操作;
遍历GX中的元素,将对应磁铁信息中的磁铁组号(或指针)改为GY,位置加上Length(GY),O(N)操作
GY合并到GX中,O(1)操作。
C命令:输出X中的位置信息
初始化时可以不创建磁铁组表,这样就要在M命令中进行判断,分别对GX和GY为空时进行处理
#2
方法二:
磁铁信息使用链接信息,同组磁铁组成链表,需要能够通过任一元素找到链表首尾,可以使用双向链,或者使用带头标志的循环链。下面用双向链为例:
初始化:所有磁铁prev=null,next=null
M命令:
找到Y所在链表首HY,O(N)
找到X所在链表尾TX,O(N)
连接两个链表,O(N)
C命令:
找到从X遍历到链表尾并计数,O(N)
可以在磁铁信息中保存“其下磁铁数”的信息以加快C命令:
在M命令的第一步时,可以计算出Y链表的长度(Y中的位置信息+遍历过的节点数)
在M命令的第二步时,先找到X所在链表首,再遍历到链表尾,所有节点的位置信息+Y链表长度
磁铁信息使用链接信息,同组磁铁组成链表,需要能够通过任一元素找到链表首尾,可以使用双向链,或者使用带头标志的循环链。下面用双向链为例:
初始化:所有磁铁prev=null,next=null
M命令:
找到Y所在链表首HY,O(N)
找到X所在链表尾TX,O(N)
连接两个链表,O(N)
C命令:
找到从X遍历到链表尾并计数,O(N)
可以在磁铁信息中保存“其下磁铁数”的信息以加快C命令:
在M命令的第一步时,可以计算出Y链表的长度(Y中的位置信息+遍历过的节点数)
在M命令的第二步时,先找到X所在链表首,再遍历到链表尾,所有节点的位置信息+Y链表长度
#3
并查集无误。合并的时候多做几步操作就是。
1L 2L的办法总复杂度都会退化到平方的。数据很好构造。
1L 2L的办法总复杂度都会退化到平方的。数据很好构造。
#4
什么情况下会退化到平方?能举个例子吗?
空间效率确实不高。
#5
还请问c++stl中有并查集的库么?
#6
仅供参考
#include <algorithm>
#include <iostream>
#include <functional>
#include <cstring>
using namespace std;
int main() {
char *Alphabet = "abcdefghijklmnopqrstuvwxyz" ;
char *Vowels = "aeiou" ;
char *AlphaNum = "0123456789abcdef" ;
char result[45] ;
char *last ;
int lenA = strlen(Alphabet) ;
int lenV = strlen(Vowels ) ;
int lenAN = strlen(AlphaNum) ;
cout << "Alphabet = " << Alphabet << endl ;
cout << "Vowels = " << Vowels << endl ;
cout << "AlphaNum = " << AlphaNum << endl ;
cout << "\nusing non-predicate versions" << endl ;
//non-predicate set_difference
last = set_difference(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_difference(Alphabet, AlphaNum) = " << result << endl ;
//non-predicate set_intersection
last = set_intersection(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_intersection(Alphabet, AlphaNum) = " << result << endl ;
//non-predicate set_symmetric_difference
last = set_symmetric_difference(Alphabet, Alphabet+lenA,
Vowels , Vowels +lenV,
result) ;
*last = 0 ;
cout << "set_symmetric_difference(Alphabet, Vowels) = " << result << endl ;
//non-predicate set_union
last = set_union(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_union(Alphabet, AlphaNum) = " << result << endl ;
cout << "\nusing predicate versions" << endl ;
//predicate set_difference
last = set_difference(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_difference(Alphabet, AlphaNum) = " << result << endl ;
//predicate set_intersection
last = set_intersection(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_intersection(Alphabet, AlphaNum) = " << result << endl ;
//predicate set_symmetric_difference
last = set_symmetric_difference(Alphabet, Alphabet+lenA,
Vowels , Vowels +lenV,
result , less<char>()) ;
*last = 0 ;
cout << "set_symmetric_difference(Alphabet, Vowels) = " << result << endl ;
//predicate set_union
last = set_union(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_union(Alphabet, AlphaNum) = " << result << endl ;
return 0 ;
}
#7
我去研究一下!
#1
方法一:数据分为两部分,磁铁数组和磁铁组表。
磁铁数组包含所有磁铁信息,磁铁信息中有磁铁组号(或指针)、该铁在组中的位置(就是其下有多少磁铁。
磁铁组是个线性表,元素是磁铁号,只要求遍历、添加、合并功能,用链表实现。
初始化:所有磁铁,位置为0;为所有磁铁创建单元磁铁组表。
M命令:找到X所在磁铁组GX、,O(1)操作;
找到Y所在磁铁组GY,O(1)操作;
遍历GX中的元素,将对应磁铁信息中的磁铁组号(或指针)改为GY,位置加上Length(GY),O(N)操作
GY合并到GX中,O(1)操作。
C命令:输出X中的位置信息
初始化时可以不创建磁铁组表,这样就要在M命令中进行判断,分别对GX和GY为空时进行处理
磁铁数组包含所有磁铁信息,磁铁信息中有磁铁组号(或指针)、该铁在组中的位置(就是其下有多少磁铁。
磁铁组是个线性表,元素是磁铁号,只要求遍历、添加、合并功能,用链表实现。
初始化:所有磁铁,位置为0;为所有磁铁创建单元磁铁组表。
M命令:找到X所在磁铁组GX、,O(1)操作;
找到Y所在磁铁组GY,O(1)操作;
遍历GX中的元素,将对应磁铁信息中的磁铁组号(或指针)改为GY,位置加上Length(GY),O(N)操作
GY合并到GX中,O(1)操作。
C命令:输出X中的位置信息
初始化时可以不创建磁铁组表,这样就要在M命令中进行判断,分别对GX和GY为空时进行处理
#2
方法二:
磁铁信息使用链接信息,同组磁铁组成链表,需要能够通过任一元素找到链表首尾,可以使用双向链,或者使用带头标志的循环链。下面用双向链为例:
初始化:所有磁铁prev=null,next=null
M命令:
找到Y所在链表首HY,O(N)
找到X所在链表尾TX,O(N)
连接两个链表,O(N)
C命令:
找到从X遍历到链表尾并计数,O(N)
可以在磁铁信息中保存“其下磁铁数”的信息以加快C命令:
在M命令的第一步时,可以计算出Y链表的长度(Y中的位置信息+遍历过的节点数)
在M命令的第二步时,先找到X所在链表首,再遍历到链表尾,所有节点的位置信息+Y链表长度
磁铁信息使用链接信息,同组磁铁组成链表,需要能够通过任一元素找到链表首尾,可以使用双向链,或者使用带头标志的循环链。下面用双向链为例:
初始化:所有磁铁prev=null,next=null
M命令:
找到Y所在链表首HY,O(N)
找到X所在链表尾TX,O(N)
连接两个链表,O(N)
C命令:
找到从X遍历到链表尾并计数,O(N)
可以在磁铁信息中保存“其下磁铁数”的信息以加快C命令:
在M命令的第一步时,可以计算出Y链表的长度(Y中的位置信息+遍历过的节点数)
在M命令的第二步时,先找到X所在链表首,再遍历到链表尾,所有节点的位置信息+Y链表长度
#3
并查集无误。合并的时候多做几步操作就是。
1L 2L的办法总复杂度都会退化到平方的。数据很好构造。
1L 2L的办法总复杂度都会退化到平方的。数据很好构造。
#4
什么情况下会退化到平方?能举个例子吗?
空间效率确实不高。
#5
还请问c++stl中有并查集的库么?
#6
仅供参考
#include <algorithm>
#include <iostream>
#include <functional>
#include <cstring>
using namespace std;
int main() {
char *Alphabet = "abcdefghijklmnopqrstuvwxyz" ;
char *Vowels = "aeiou" ;
char *AlphaNum = "0123456789abcdef" ;
char result[45] ;
char *last ;
int lenA = strlen(Alphabet) ;
int lenV = strlen(Vowels ) ;
int lenAN = strlen(AlphaNum) ;
cout << "Alphabet = " << Alphabet << endl ;
cout << "Vowels = " << Vowels << endl ;
cout << "AlphaNum = " << AlphaNum << endl ;
cout << "\nusing non-predicate versions" << endl ;
//non-predicate set_difference
last = set_difference(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_difference(Alphabet, AlphaNum) = " << result << endl ;
//non-predicate set_intersection
last = set_intersection(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_intersection(Alphabet, AlphaNum) = " << result << endl ;
//non-predicate set_symmetric_difference
last = set_symmetric_difference(Alphabet, Alphabet+lenA,
Vowels , Vowels +lenV,
result) ;
*last = 0 ;
cout << "set_symmetric_difference(Alphabet, Vowels) = " << result << endl ;
//non-predicate set_union
last = set_union(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result) ;
*last = 0 ;
cout << "set_union(Alphabet, AlphaNum) = " << result << endl ;
cout << "\nusing predicate versions" << endl ;
//predicate set_difference
last = set_difference(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_difference(Alphabet, AlphaNum) = " << result << endl ;
//predicate set_intersection
last = set_intersection(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_intersection(Alphabet, AlphaNum) = " << result << endl ;
//predicate set_symmetric_difference
last = set_symmetric_difference(Alphabet, Alphabet+lenA,
Vowels , Vowels +lenV,
result , less<char>()) ;
*last = 0 ;
cout << "set_symmetric_difference(Alphabet, Vowels) = " << result << endl ;
//predicate set_union
last = set_union(Alphabet, Alphabet+lenA,
AlphaNum, AlphaNum+lenAN,
result , less<char>()) ;
*last = 0 ;
cout << "set_union(Alphabet, AlphaNum) = " << result << endl ;
return 0 ;
}
#7
我去研究一下!