如题。
目录
例题一 “List”
例题二 “自己实现bitset”
例题一 “List”
【描述】
写一个程序完成以下命令:
new id
——新建一个指定编号为id的序列(id<10000)
add id num
——向编号为id的序列加入整数num
merge id1 id2
——合并序列id1和id2中的数,并将id2清空
unique id
——去掉序列id中重复的元素
out id
——从小到大输出编号为id的序列中的元素,以空格隔开
总时间限制: 4000ms 内存限制: 65536kB
【输入】
第一行一个数n,表示有多少个命令( n<=200000)。以后n行每行一个命令。
【输出】
按描述要求输出。
【样例输入】
16
new 1
new 2
add 1 1
add 1 2
add 1 3
add 2 1
add 2 2
add 2 3
add 2 4
out 1
out 2
merge 1 2
out 1
out 2
unique 1
out 1
【样例输出】
1 2 3
1 2 3 4
1 1 2 2 3 3 4
1 2 3 4
【来源】OJ
【说明】以上操作中耗时最多的是merge
。笔者首先尝试了multiset<int>
模板,要么超时要么超过空间限制,最后用list<int>
通过。
【超时的版本】
#include <iostream>
#include <iomanip>
#include <set>
#include <string>
#include<vector>
using namespace std;
void readin();
void Mynew(int id);
void Myadd(int id, int num);
void Mymerge(int id1, int id2);
void Myunique(int id1);
void Myout(int id1);
vector<multiset<int> >A(128);
int main() {
int nComman = 0; cin >> nComman;
for(int i = 0; i < nComman; ++i)readin();
return 0;
}
void readin() {
string temp; int op1=0, op2=0;
cin >> temp;
if(temp == "new") { cin >> op1; getchar(); Mynew(op1); return; }
else if(temp == "add") {
cin >> op1 >> op2; getchar(); Myadd(op1, op2); return;
}
else if(temp == "merge") {
cin >> op1 >> op2; getchar(); Mymerge(op1, op2); return;
}
else if(temp == "unique") {
cin >> op1; getchar(); Myunique(op1); return;
}
else if(temp == "out") {
cin >> op1; getchar(); Myout(op1); return;
}
}
void Mynew(int id) {
if(A.size() < id) { A.push_back(multiset<int>()); }
return;
}
void Myadd(int id, int num){
A[id].insert(num);
return;
}
void Mymerge(int id1, int id2) {
A[id1].insert(A[id2].begin(), A[id2].end());
A[id2].erase(A[id2].begin(), A[id2].end());
return;
}
void Myunique(int id1) {
set<int>temp(A[id1].begin(), A[id1].end());
A[id1].erase(A[id1].begin(), A[id1].end());
A[id1].insert(temp.begin(), temp.end());
return;
}
void Myout(int id1) {
for(auto i = A[id1].begin(); i != A[id1].end(); ++i) {
cout << *i << " ";
}
return;
}
【通过的版本】
#include <iostream>
#include <iomanip>
#include <set>
#include <string>
#include<vector>
#include<list>
using namespace std;
void readin();
void Mynew(int n);
void Myadd(int id1, int num);
void Mymerge(int id1, int id2);
void Myunique(int id1);
void Myout(int id1);
vector<list<int> >A(32);
int main() {
int nComman = 0; cin >> nComman;
for(int i = 0; i < nComman; ++i)readin();
return 0;
}
void readin() {
string temp; int op1 = 0, op2 = 0;
cin >> temp;
if(temp == "new") { cin >> op1; getchar(); Mynew(op1); return; }
else if(temp == "add") {
cin >> op1 >> op2; getchar(); Myadd(op1, op2); return;
}
else if(temp == "merge") {
cin >> op1 >> op2; getchar(); Mymerge(op1, op2); return;
}
else if(temp == "unique") {
cin >> op1; getchar(); Myunique(op1); return;
}
else if(temp == "out") {
cin >> op1; getchar(); Myout(op1); return;
}
}
void Mynew(int n)
{
if(A.size() < n+1)A.push_back(list<int>());
return;
}
void Myadd(int id1, int num)
{
A[id1].push_back(num); return;
}
void Mymerge(int id1, int id2)
{
A[id1].merge(A[id2]);
return;
}
void Myunique(int id1)
{
set<int>temp(A[id1].begin(), A[id1].end());
A[id1].clear();
for(auto i = temp.begin(); i != temp.end(); ++i) {
A[id1].push_back(*i);
}
return;
}
void Myout(int id1)
{
A[id1].sort();
for(auto i = A[id1].begin(); i != A[id1].end(); ++i) { cout << *i << ' '; }
cout << '\n';
return;
}
【注】这道题反映了不同容器性能的显著差别。
例题二 “自己实现bitset”
【描述】程序填空,实现一个类似STL bitset的 MyBitset, 输出指定结果。
#include <iostream>
#include <cstring>
using namespace std;
template <int bitNum>
struct MyBitset
{
char a[bitNum/8+1];
MyBitset() { memset(a,0,sizeof(a));};
void Set(int i,int v) {
char & c = a[i/8];
int bp = i % 8;
if( v )
c |= (1 << bp);
else
c &= ~(1 << bp);
}
//************************************
//*********在此处补充你的代码*********
//************************************
void Print() {
for(int i = 0;i < bitNum; ++i)
cout << (*this) [i];
cout << endl;
}
};
int main()
{
int n;
int i,j,k,v;
while( cin >> n) {
MyBitset<20> bs;
for(int i = 0;i < n; ++i) {
int t;
cin >> t;
bs.Set(t,1);
}
bs.Print();
cin >> i >> j >> k >> v;
bs[k] = v;
bs[i] = bs[j] = bs[k];
bs.Print();
cin >> i >> j >> k >> v;
bs[k] = v;
(bs[i] = bs[j]) = bs[k];
bs.Print();
}
return 0;
}
【输入】
多组数据
每组数据:
第一行是整数 n , 1 <= n < 20;
第二行是n个整数 k1,k2… kn,均在范围 [0,19]内。
第三行是 四个整数 i1,j1,k1,v1 。 0 <= i1,j1,k1 <= 19, v1值为0或1
第三行是 四个整数 i2,j2,k2,v2 。 0 <= i2,j2,k2 <= 19, v2值为0或1
【输出】
对每组数据,共输出3行,每行20位,每位为1或者0。最左边称为第0位
第一行: 第 k1,k2 … kn位为1,其余位为0。
第二行: 将第一行中的第 i1,j1,k1位变为 v1,其余位不变
第三行: 将第二行中的第i2位和k2位变为v2,其余位不变
【样例输入】
4
0 1 2 8
7 19 0 1
7 2 8 0
1
1
1 1 1 0
1 1 1 1
【样例输出】
11100000100000000000
11100001100000000001
11100000000000000001
01000000000000000000
00000000000000000000
01000000000000000000
【来源】OJ
【出题人注】推荐使用内部类,内部类中使用引用成员。引用成员要在构造函数中初始化。
【解】
class ret;
friend class ret;
class ret {
friend struct MyBitset;
public:
int n;//第几位
MyBitset* out;//指向数组
ret(MyBitset& my_, int n_) {
out = &my_;
n = n_;
}
ret& operator=(const ret& r) {
bool temp = (r.out->a[r.n / 8] >> (r.n % 8)) & 1;
out->Set(n, temp);
return *this;
}
ret& operator=(bool i) {
out->Set(n, i);
return *this;
}
friend ostream& operator<<(ostream& os_, const ret& r)
{
int tempv = ((r.out->a[r.n / 8]) >> (r.n % 8)) & 1;
os_ << tempv; return os_;
}
};
ret operator[](int n_) {
return ret(*this, n_);
}
【注】十分建议查询<bitset>
文件并借鉴其实现方式。
内部类应包含数组位置和数据位置两个信息;
如果在内部类中包含MyBitset*
指针,则可以调用其中的Set()
函数。相比之下,包含char*
指针直接指向原数组就无此功能。