PTA天梯模拟补题2

目录

L1-3 阅览室(20)

L1-6 整除光棍(20) 

L1-8 矩阵A乘以B(15) 

L2-2 重排链表(25)

L2-3 图着色问题(25) (DFS)

L3-1 二叉搜索树的结构(30)  (二叉搜索树+string)

L3-2 森森快递(30) (贪心+线段树区间修改&区间查询)


L1-3 阅览室(20)

注意:开始时间可能为0,mp初始化需为-1 

#include<bits/stdc++.h>
using namespace std;
const int N = 10005;
int n;
int nm,t1,h,m;
char c;
double cnt,sum;
int mp[N];
int main(){
	scanf("%d",&n);
	while(n--){
        cnt=sum=0;
		memset(mp,-1,sizeof(mp));//更新开始时间
		while(1){
		
			scanf("%d %c",&nm,&c);
			scanf("%2d:%2d",&h,&m);
			if(nm==0)break;
			
			if(c=='E'){
				if(mp[nm]==-1)continue;
				else{
					cnt++;
					sum+=h*60+m-mp[nm];
					mp[nm]=-1;
				}
			}else{
				mp[nm]=h*60+m;
			}
		}if(cnt!=0)printf("%.lf %.lf\n",cnt,1.0*(sum+0.5)/cnt);
		else printf("0 0\n");
		
	}
	return 0;
}

L1-6 整除光棍(20) 

 模拟除法,如111/23,1111/345,当11...1>x 时开始除法

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn = 1e3 + 10;
int x,n,m=1;
int main(){
    scanf("%d",&x);
    while(m<x){
    	n++;m=m*10+1;
	}while(1){
		printf("%d",int(m/x));
		n++;
		if(m%x==0)break;
		m=m%x*10+1;
	}printf(" %d",n);
    return 0;
}

L1-8 矩阵A乘以B(15) 

 注意:Ca和Rb要输出数字

#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
int r1,c1,r2,c2,r3,c3;
int a[N][N],b[N][N],c;
int main(){
	scanf("%d%d",&r1,&c1);
	for(int i=1;i<=r1;i++){
		for(int j=1;j<=c1;j++){
			scanf("%d",&a[i][j]);
		}
	}
	scanf("%d%d",&r2,&c2);
	if(c1!=r2){
		printf("Error: %d != %d",c1,r2);
		return 0;
	}
	for(int i=1;i<=r2;i++){
		for(int j=1;j<=c2;j++){
			scanf("%d",&b[i][j]);
		}
	}
	printf("%d %d\n",r1,c2);
	for(int i=1;i<=r1;i++){
		for(int j=1;j<=c2;j++){
            c=0;
			for(int k=1;k<=c1;k++){
				c+=a[i][k]*b[k][j];
			}printf("%d",c);
			if(j!=c2)printf(" ");
		}if(i!=r1)printf("\n");
	}
	
	return 0;
}

L2-2 重排链表(25)

a[N]:记录调整顺序前的链表每个节点的地址

b[N]:记录调整顺序后的链表每个节点的地址 

输出时只需要知道当前节点的地址和下一节点的地址即可,数据可根据映射关系查询

注意:给出的n个节点可能不连续,所以更改顺序以及输出时用cnt做限制

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int idx,n;
struct node{
    int data,nxt;
}mp[N];
int a[N],b[N];
int main(){
    scanf("%d%d",&idx,&n);
    for(int i=1;i<=n;i++){
        int x;scanf("%d",&x);
        scanf("%d%d",&mp[x].data,&mp[x].nxt);
    }
	int t=mp[idx].nxt;
	int cnt=0;
	a[++cnt]=idx;
    
    while(t!=-1){
    	a[++cnt]=t;
    	t=mp[t].nxt;
	}int front=1,rear=cnt;
	cnt=0;
	while(front<=rear){
		b[++cnt]=a[rear--];
		if(front<=rear)
            b[++cnt]=a[front++];
	}for(int i=1;i<=cnt;i++){
		if(i!=cnt)
			printf("%05d %d %05d\n",b[i],mp[b[i]].data,b[i+1]);
		else 
			printf("%05d %d -1",b[i],mp[b[i]].data);
	}
    return 0;
}

L2-3 图着色问题(25) (DFS)

 无向图DFS逐个搜索

注意:要求正好k个颜色

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn = 1e3 + 10;
int n,m,k,x,y,q,vis[maxn],v[maxn];
vector<int>edge[maxn];
int f=1;
void dfs(int x){
	vis[x]=1;
	for(auto i:edge[x]){
		if(v[i]==v[x]){
			f=0;return;
	    }if(vis[i])continue;
		//vis[i]=1;
		dfs(i);
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		edge[x].push_back(y);
		edge[y].push_back(x);
	}
	scanf("%d",&q);
	while(q--){
		set<int>ss;
		for(int i=1;i<=n;i++){
			scanf("%d",&v[i]);
			ss.insert(v[i]);
		}if(ss.size()!=k){
            printf("No\n");
            continue;
        }ss.clear();
		f=1;
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
            dfs(i);
		if(f)printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

L3-1 二叉搜索树的结构(30)  (二叉搜索树+string)

 map中.count(x):查找键值x是否存在,存在返回1,不存在返回0

string中.find("s"):查找字符串中“s”是否出现,出现返回索引,未出现返回-1

sscanf(s.c_str()," ");  string字符串输入

取对数:log(x)/log(2) 以2为底 x的对数

注意:需要判断题目给出的数值q1,q2是否在所给树中

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
int n,rt,t,m;
int a[N],v[N];
map<int,int>ani;
void add(int id,int x){
	if(!v[id]){
		a[id]=x,v[id]=1;
        ani[x]=id;
		return;
	}if(x<a[id])add(id*2,x);
	else add(id*2+1,x);
}
int main(){
	
	scanf("%d%d",&n,&rt);
	add(1,rt);
	for(int i=2;i<=n;i++){
		scanf("%d",&t);
		add(1,t);
	}
	scanf("%d",&m);
	
	int q1,q2;
	while(m--){
		q1=q2=0;
		scanf("%d",&q1);
		string ss;
		getline(cin,ss);
		//cout<<ss<<endl;
		int f=0;
		if(!ani.count(q1)){
            printf("No\n");
            continue;
        }
		if(ss.find("root")!=-1){
			if(q1==rt)f=1;
		}else if(ss.find("parent")!=-1){
			sscanf(ss.c_str()," is the parent of %d",&q2);
			if(ani.count(q2)&&int(ani[q1])==(ani[q2]/2))f=1;
		}else if(ss.find("left")!=-1){
			sscanf(ss.c_str()," is the left child of %d",&q2);
			if(ani.count(q2)&&ani[q1]==ani[q2]*2)f=1;
		}else if(ss.find("right")!=-1){
			sscanf(ss.c_str()," is the right child of %d",&q2);
			if(ani.count(q2)&&ani[q1]==ani[q2]*2+1)f=-1;
		}
		else{
			if(ss.find("siblings")!=-1){
				sscanf(ss.c_str()," and %d are siblings",&q2);
				if(ani.count(q2)&&ani[q1]/2==ani[q2]/2)f=1;
			}else if(ss.find("level")!=-1){
				sscanf(ss.c_str()," and %d are on the same level",&q2);
				if(ani.count(q2)){
					int tp1=log(ani[q1])/log(2);
					int tp2=log(ani[q2])/log(2);
					if(tp1==tp2)f=1;
				}
			}
		}if(f)printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

  

L3-2 森森快递(30) (贪心+线段树区间修改&区间查询)

贪心,要想得到最大的运输重量,就要贪心地找最大的不想交的区间数目(因为如果相交,那么在这两段相交区间上运的货物就要共同占用公路的最大运送量)

按右端点升序排序,(如下图,取自: 区间覆盖问题 - 贪心_有n个互相不重叠的区间,问最大覆盖面积),用线段树维护区间的最小值,然后每选一个区间,把这个区间的最小值(tmp)查询一下,若tmp>0则可运,modify更新区间值减去x

 val:节点i记录从i-1到i能运输的重量 ,更新为0
minv:记录子树最小运输重量 
query:区间查询起点到终点最小值是否>0 
modify:区间修改 t标记下放减去最小值 
节点只需记录标记和最小值,无需info  

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lson id*2,l,m
#define rson id*2+1,m+1,r
const int N = 1e5 + 5;
int n, q;
ll sum;
struct s_t{
	int s,t,c;
	bool operator<(const s_t&b)const{
		//if(c!=b.c)return c<b.c;
		if(t!=b.t)return t<b.t;
		return s<b.s;
	}
}a[N];
//val:节点i记录从i-1到i能运输的重量 ,更新为0
//minv:记录子树最小运输重量 
//query:区间查询起点到终点最小值是否>0 
//modify:区间修改 t标记下放减去最小值 
//节点只需记录标记和最小值,无需info 
struct node{
	int t;
	int minv;
}seg[N*4];

void update(int id){
	seg[id].minv=min(seg[id*2].minv,seg[id*2+1].minv);
}
void settag(int id,int t){
	seg[id].minv+=t;
	seg[id].t+=t;
}
void pushdown(int id){
	if(seg[id].t!=0){
		settag(id*2,seg[id].t);
		settag(id*2+1,seg[id].t);
		seg[id].t=0;
	}
}
void build(int id,int l,int r){
	if(l==r){
		scanf("%d",&seg[id].minv);
		seg[l].t=0;
		//printf("seg[%d].minv:%d\n",l,seg[l].minv);
		return;
	}int m=(l+r)/2;
	build(lson);
	build(rson);
	update(id);
	//printf("seg[%d].minv:%d\n",l,seg[l].minv);
}
int query(int id,int l,int r,int ql,int qr){
	//printf("[%d,%d]\n",l,r);
	//printf("seg[%d].minv:%d\n",id,seg[id].minv);
	if(ql==l&&qr==r) {
		
		return seg[id].minv;
	}
	pushdown(id);
	int m=(l+r)/2;
	if(qr<=m) return query(lson,ql,qr);
	else if(ql>m)return query(rson,ql,qr);
	else return min(query(lson,ql,m),query(rson,m+1,qr));
}
void modify(int id,int l,int r,int ml,int mr,int t){
	if(ml==l&&mr==r){
		settag(id,t);
		return;
	}pushdown(id);
	int m=(l+r)/2;
	if(mr<=m)modify(lson,ml,mr,t);
	else if(ml>m)modify(rson,ml,mr,t);
	else modify(lson,ml,m,t),modify(rson,m+1,mr,t);
	update(id);
}
int main() {
	scanf("%d %d", &n, &q);
	build(1, 1, n-1);
	for(int i=1;i<=q;i++){
		int s,t;
		scanf("%d%d",&s,&t);
		if(s>t)swap(s,t);
		a[i]=(s_t){s+1,t,t-s};
	}sort(a+1,a+q+1);
	for(int i=1;i<=q;i++){
		int tmp=query(1,1,n-1,a[i].s,a[i].t);
		//printf("a[%d].s:%d .t:%d tmp:%d\n",i,a[i].s,a[i].t,tmp);
		if(tmp>0){
			sum+=tmp;
			modify(1,1,n-1,a[i].s,a[i].t,-tmp);
		}
	}printf("%lld",sum);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值