0
点赞
收藏
分享

微信扫一扫

GPLT-天梯赛 (较复杂的数据结构题1)

杰森wang 2022-04-17 阅读 53
数据结构

1、L2-022 重排链表 (25 分)
在这里插入图片描述
思路:纯纯的数据结构题,我的做法是先用结构体存下来,然后再用数组模拟存节点,最后处理一下空节点就可以了,模拟题。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
struct node{
	int val;
	int nextx;
}t[maxn];
int st,n;
vector<int> v;
int main(){
	scanf("%d%d",&st,&n);
	for(int i=1; i<=n; i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		t[x].val=y,t[x].nextx=z;
	}
	int x=st;
	while(x!=-1){
		v.push_back(x);
		x=t[x].nextx;
	}
	int k=v.size();
	if(k&1){
		vector<int> vx;
		int i,j;
		for(i=0,j=k-1; i!=j; i++,j--){
			vx.push_back(v[j]);
			vx.push_back(v[i]);
		}
		vx.push_back(v[j]);
		for(i=0; i<vx.size()-1; i++){
			printf("%05d %d %05d\n",vx[i],t[vx[i]].val,vx[i+1]);
		}
		printf("%05d %d -1",vx[i],t[vx[i]].val);
	}
	else{
		vector<int> vx;
		int i,j;
		for(i=0,j=k-1; i<j; i++,j--){
			vx.push_back(v[j]);
			vx.push_back(v[i]);
		}
		for(i=0; i<vx.size()-1; i++){
			printf("%05d %d %05d\n",vx[i],t[vx[i]].val,vx[i+1]);
		}
		printf("%05d %d -1",vx[i],t[vx[i]].val);
	}
	return 0;
}

2、L2-002 链表去重 (25 分)
在这里插入图片描述
思路:这题和上面有点相似,但是难一点,我们思路还是一样,先模拟,结构体存链表,然后两个vector进行存放去重和非去重,然后注意一点是小心没有重复的,那这个时候就不能进行输出位置,所以来一个判断即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct node{
	int val;
	int nextx;
}t[maxn];
vector<int> v,vx;
int st,n;
int main(){
	scanf("%d%d",&st,&n);
	for(int i=1; i<=n; i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		t[x].val=y,t[x].nextx=z;
	}
	int x=st;
	set<int> s;
	while(x!=-1){ 
		if(s.find(abs(t[x].val))==s.end()){
			v.push_back(x);
			s.insert(abs(t[x].val));
		}
		else{
			vx.push_back(x);
		}
		x=t[x].nextx;
	}
	for(int i=0; i<v.size()-1; i++){
		printf("%05d %d %05d\n",v[i],t[v[i]].val,v[i+1]);
	}
	printf("%05d %d -1\n",v[v.size()-1],t[v[v.size()-1]].val);
	if(vx.size()!=0){//段错误的点,要判断。
		for(int i=0; i<vx.size()-1; i++){
			printf("%05d %d %05d\n",vx[i],t[vx[i]].val,vx[i+1]);
		}
		printf("%05d %d -1\n",vx[vx.size()-1],t[vx[vx.size()-1]].val);
	}
	return 0;
}

3、7-15 插入排序还是归并排序 (25 分)
在这里插入图片描述
思路:这题要求对两种排序一定十分的理解,插入排序其实就是用当前元素在已经排好的序列中寻找正确的位置并插入进去,归并排序就是分到最小长度的序列(即1个长度),然后两两、四四、八八…进行合并。

我们首先直接对b数组进行判断,找到前面第一个无序点,然后看后面的元素是否全部都与a一一对应相等,若是,则表明他是插入排序的其中一步,然后sort快排直接搞定下一步输出即可。否则,他就是归并排序了。这时,我们就需要利用快排sort进行模拟归并了:
首先定义一个下标戳i=2,然后利用另一个下标戳就j=0,不断+i进行数组排序模拟归并,中间只要判断到a与b相等,那就退出,最后再跑一次当前i长度的归并排序然后输出即可,讲起来费劲,看看代码就懂了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int n,k;
int a[maxn],b[maxn],c[maxn];
bool judge(){
	for(int i=1; i<=n; i++){
		if(a[i]!=b[i]) return true;
	}
	return false;
}
int main(){
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(int i=1; i<=n; i++) scanf("%d",&b[i]);
	for(int i=2; i<=n; i++){
		if(b[i]>=b[i-1]) continue;
		else{
			k=i;
			break;
		}
	}
	int flagx=1;
	for(int i=k; i<=n; i++){
		if(a[i]!=b[i]){
			flagx=0;
			break;
		}
	}
	if(flagx){
		puts("Insertion Sort");
		sort(b+1,b+1+k);
		for(int i=1; i<=n; i++){
			if(i!=1) printf(" ");
			printf("%d",b[i]);
		}
	}
	else{
		puts("Merge Sort");
		int i=2;
		for( ; judge(); i+=i){
			for(int j=0; j<=n; j+=i) sort(a+1+j,a+1+min(j+i,n));
			//注意一定要min,因为可能比n大了。
		}
		for(int j=0; j<=n; j+=i) sort(a+1+j,a+1+min(j+i,n));
		for(int i=1; i<=n; i++){
			if(i!=1) printf(" ");
			printf("%d",a[i]);
		}
	}
	return 0;
}

4、7-16 关于堆的判断 (25 分)
在这里插入图片描述
思路:这题其实最难的就是建堆了,要注意,我们不能从顶往下更新堆,要从低往上更新堆,这样才能够正确建堆,这点我是真的不懂,后来看别人都是从后往前更新堆那就对了。至于其他处理就很简单了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int a[maxn];
int n,m;
int cnt;
string s;
map<int,int> mp;
void build(int x){
	a[++cnt]=x;
	int t=cnt;
	while(t>1&&a[t/2]>a[t]){
		swap(a[t/2],a[t]);
		t/=2;
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++){
		int x;
		scanf("%d",&x);
		build(x);
	}
	for(int i=1; i<=n; i++) mp[a[i]]=i;
//	for(int i=1; i<=n; i++) cout << a[i] << " ";
//	puts("");	
	getchar();
	while(m--){
		getline(cin,s);
		if(s.find("root")!=-1){
			int k=s.find(" ");
			int x=stoi(s.substr(0,k));
//			cout << x << endl;
			if(mp[x]==1) puts("T");
			else puts("F");
		}
		else if(s.find("siblings")!=-1){
			int k=s.find("and");
			int kk=s.find("are");
			int x=stoi(s.substr(0,k-1));
			int y=stoi(s.substr(k+4,kk-k-4));
//			cout << x << " " << y << endl;
			if(mp[x]/2==mp[y]/2) puts("T");
			else puts("F");
		}
		else if(s.find("parent")!=-1){
			int k=s.find(" ");
			int kk=s.find("of");
			int x=stoi(s.substr(0,k));
			int y=stoi(s.substr(kk+3,s.size()));
//			cout << x << " " << y << endl;
			if(mp[x]==mp[y]/2) puts("T");
			else puts("F");
		}
		else if(s.find("child")!=-1){
			int k=s.find(" ");
			int kk=s.find("of");
			int x=stoi(s.substr(0,k));
			int y=stoi(s.substr(kk+3,s.size()));
//			cout << x << " " << y << endl;
			if(mp[y]==mp[x]/2) puts("T");
			else puts("F");
		}
	}
	return 0;
}

5、7-15 清点代码库 (25 分)在这里插入图片描述

思路:这题是map和multimap的综合应用,注意vector是可以当做map的一个元素的,先用map计数,然后再用multimap进行输出即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
multimap<int,vector<int>,greater<int> > mp;
map<vector<int>,int>mpx;
int n,m;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1; i<=n; i++){
		vector<int> v;
		for(int j=1; j<=m; j++){
			int x;
			scanf("%d",&x);
			v.push_back(x);
		}
		mpx[v]++;
	}
	for(auto i:mpx){
		mp.insert({i.second,i.first});
	}
	printf("%d\n",mp.size());
	for(auto i:mp){
		printf("%d",i.first);
		for(auto j:i.second){
			printf(" %d",j);
		}
		puts("");
	}
	return 0;
}

6、7-14 冰岛人 (25 分)
在这里插入图片描述
思路:这道题是一道模拟题,难点在于理解他的话,“所谓“五代以内无公共祖先”是指两人的公共祖先(如果存在的话)必须比任何一方的曾祖父辈分高。”这句话的意思是如果a的第三代祖先和b的第六代祖先相同,那也算是有公共祖先,真的恶心。然后注意一下没有祖先的map不要标记为-1就可以,我也不知道为什么会错。整题就是map的一个大模拟,就很恶心。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int n,m,cnt;
map<string,string> mp;//father
map<string,int> mpx;//sex
map<string,int> mpxx;//flag
bool judge(string s1, string s2){
	int i=1;
	for(string a=s1; !a.empty(); a=mp[a],i++){
		int j=1;
		for(string b=s2; !b.empty(); b=mp[b],j++){
			if(i>=5&&j>=5) return true;
			if((i<5||j<5)&&a==b) return false;
 		}
	}
	return true;
}
int main(){
	cin >> n;
	for(int i=1; i<=n; i++){
		string s1,s2;
		cin >> s1 >> s2;
		mpxx[s1]=1;
		if(s2[s2.size()-1]=='n'){
			mp[s1]=s2.substr(0,s2.size()-4);
			mpx[s1]=1;
//			cout << mp[s1] << " " << mpx[s1] << endl;
		}
		else if(s2[s2.size()-1]=='r'){
			mp[s1]=s2.substr(0,s2.size()-7);
			mpx[s1]=-1;
//			cout << mp[s1] << " " << mpx[s1] << endl;
		}
		else if(s2[s2.size()-1]=='m'){
			mpx[s1]=1;
// 			mp[s1]="-1";
//			cout << mp[s1] << " " << mpx[s1] << endl;
		} 
		else if(s2[s2.size()-1]=='f'){
			mpx[s1]=-1;
// 			mp[s1]="-1";
//			cout << mp[s1] << " " << mpx[s1] << endl;
		} 
	}
	cin >> m;
	for(int i=1; i<=m; i++){
		string s1,s2,s3,s4;
		cin >> s1 >> s2 >> s3 >> s4;
//		cout << mp[s1] << " " << mp[s3] << endl;
//		cout << mpxx[s1] << " " << mpxx[s3] << endl;
		if(mpxx[s1]!=1||mpxx[s3]!=1) puts("NA");
        else if(mpx[s1]==mpx[s3]) puts("Whatever");
		else{
			if(judge(s1,s3)) puts("Yes");
			else puts("No");
		}
	}
	return 0;
}

7、7-15 口罩发放 (25 分)
在这里插入图片描述
思路:注意这一题,读题相当重要,首先就是id合法性,两个输出都要合法的id,注意最后一句话的意思是全部输出健康值为1的,不是输出每天健康值都为1的。

23分的题解
不知道到底错哪了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int d,p;
map<string,int> mp;//shijian
map<int,string> sx;
map<string,int> sxx;
map<string,string> namex;
struct node{
	string name;
	string id;
	int fine;
	int time;
}t[maxn];
bool judge(string s){
	if(s.size()!=18) return false;
	for(int i=0; i<18; i++){
		if(!isdigit(s[i])) return false;
 	}
 	return true;
}
int main(){
	scanf("%d%d",&d,&p);
	int cntx=0;
	for(int i=1; i<=d; i++){
		int tt,s;
		scanf("%d%d",&tt,&s);
		multimap<int,string> mpx;
		if(!mp.empty()){
			for(auto j:mp){
				if(j.second!=0) mp[j.first]=j.second-1;
			}
		}
		for(int j=1; j<=tt; j++){
			cin >> t[j].name >> t[j].id >> t[j].fine;
			int x,y;
			scanf("%d:%d",&x,&y);
			t[j].time=x*60+y;
			namex[t[j].id]=t[j].name;
			if(t[j].fine==1&&judge(t[j].id)&&(sxx.find(t[j].id)==sxx.end()||sxx[t[j].id]==0)){
				sx[++cntx]=t[j].id;
				sxx[t[j].id]=1;
			}
//			cout << t[j].id.size() << endl;
		}
		for(int j=1; j<=tt; j++){
			if(judge(t[j].id)&&(mp.find(t[j].id)==mp.end()||mp[t[j].id]==0)){
//				cout << j << " " << t[j].time << endl;
				mpx.insert({t[j].time,t[j].id});
			}
		}
//		puts("");
//		for(auto j:mpx){
//			cout << j.first << " " << j.second << endl;
//		}
//		puts("");
		int cnt=0;
		for(auto j:mpx){
			if(cnt==s) break;
			if(mp.find(j.second)==mp.end()||mp[j.second]==0) cout << namex[j.second] << " " << j.second << endl;
			mp[j.second]=p+1;
			cnt++;
		}
	}
	for(auto i:sx){
		cout << namex[i.second] << " " << i.second << endl;
	}
//	if(mp.find("123456789012345670")!=mp.end()) puts("****************");
	return 0;
}

满分

#include <bits/stdc++.h>
#define MAX 0x3f3f3f3f
using  namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int d,p,s,t;
string s1,s2,s3;
map<string,int> mp;
map<string,int> mpx;
int f,cnt;
struct node{
	string name;
	string id;
	int time;
	int x;
}a[maxn],b[maxn];
bool cmp(node x, node y){
	if(x.time==y.time) return x.x<y.x;
	return x.time<y.time;
}
bool check(string s){
	if(s.size()!=18) return false;
	for(int i=0; i<s.size(); i++){
		if(!isdigit(s[i])) return false;
	}
	return true;
}
int main(){
	scanf("%d%d",&d,&p);
	for(int j=1; j<=d; j++){
		scanf("%d%d",&t,&s);
		for(int i=0; i<t; i++){
			cin >> s1 >> s2 >> f >> s3;
			a[i].name=s1,a[i].id=s2,a[i].time=(((s3[0]-48)*10+(s3[1]-48))*60+(s3[3]-48)*10+(s3[4]-48)),a[i].x=i;
			if(mp.find(a[i].id)==mp.end()) mp[a[i].id]=0;
			if(f==1&&check(a[i].id)&&mpx.find(a[i].id)==mpx.end()){
				mpx[s2]=0;
				b[cnt++]=a[i];
			}
		}
		sort(a,a+t,cmp);
		int ans=0;
		for(int i=0; i<t&&ans<s; i++){
			if(check(a[i].id)&&(mp[a[i].id]+p+1<=j||mp[a[i].id]==0)){
				cout << a[i].name << " " << a[i].id << endl;
				mp[a[i].id]=j;
				ans++;
			}
		}
	}
	for(int i=0; i<cnt; i++){
		cout << b[i].name << " " << b[i].id << endl;
	}
	return 0;
}

这道题,我只能说真的很恶心!!!!!!

举报

相关推荐

0 条评论