C++程序设计趣题:STL

如题。


目录

例题一 “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*指针直接指向原数组就无此功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值