【PAT】卡时专题

https://www.patest.cn/contests/pat-a-practise/1055

N=10^5,询问有10^3个,肯定超。并且每个询问都要按序输出前100个值,排序策略不当(区间内的值全部sort再取前k个)更加超。想办法降复杂度。

方法①(由年龄最多200种的约束):先对N个人按年龄划分,每个年龄的人各自排序。对于每个询问for(100次),每次找前第i个值时都for一遍区间内所有的年龄,找到一个最符合的,取出来放到第i个值,并且指针+1。这样复杂度就减少为:1000*100*200.

#include <bits/stdc++.h> 
using namespace std;   
struct node{
	string a;
	int c;
	bool operator < (const node &X) const{
		if(c!=X.c)
			return c>X.c;
		return a<X.a; //如果是char* a; 二维char数组是不能正确排序的 
	}
};
vector<node> v[205];
int main(){   
    int n,m,a,k,cnt=0; 
    scanf("%d%d",&n,&m);
    string x;
    int b,c;
    for(int i=0;i<n;++i){
    	cin>>x>>b>>c; 
    	v[b].push_back({x,c}); 
    } 
    for(int i=1;i<=200;++i){
    	sort(v[i].begin(),v[i].end());
    }
    while(m--){
    	printf("Case #%d:\n",++cnt);
    	scanf("%d%d%d",&k,&a,&b);
    	int id[205]={0};
    	int num=0;
    	while(k--){
    		int maxx=-100000000;
    		string minn;
    		int p=-1;
    		for(int i=a;i<=b;++i){
    			if(id[i]==v[i].size()) continue;
    			if(v[i][id[i]].c>maxx||
					v[i][id[i]].c==maxx&&i<p||
					v[i][id[i]].c==maxx&&i==p&&v[i][id[i]].a<minn){
    				maxx=v[i][id[i]].c;
    				minn=v[i][id[i]].a;
    				p=i;
    			}
    		}
    		if(p!=-1){
    			cout<<v[p][id[p]].a<<" ";
			printf("%d %d\n",p,v[p][id[p]].c);//注意!写成cout就超时 
    			id[p]++;
    			num++;
    		}
    	}
    	if(num==0)
    		printf("None\n");  
    }
    return 0;   
}
方法②(由每个询问按序输出最多100个值的约束):

因为最多也就取前100个,那么先对N个人总体排序,此时N=100000。再把每种年龄的人里面排100名以后的人都去掉,那么每次询问找前100个人中的第i个的最坏情况(跳过前面所有人找最后一个)也就:200*100,而不再是100000。

#include <bits/stdc++.h> 
using namespace std;   
struct node{
	string a;
	int b,c;
	bool operator < (const node &X) const{
		if(c!=X.c)
			return c>X.c;
		else if(b!=X.b)
			return b<X.b;
		return a<X.a; //如果是char* a; 二维char数组是不能正确排序的 
	}
};
vector<node> v,vv;
int main(){   
    int n,m,a,k,cnt=0; 
    scanf("%d%d",&n,&m);
    string x;
    int b,c;
    for(int i=0;i<n;++i){
    	cin>>x>>b>>c; 
    	v.push_back({x,b,c}); 
    } 
    sort(v.begin(),v.end());
    int id[205]={0};
    for(int i=0;i<v.size();++i){
    	id[v[i].b]++;
    	if(id[v[i].b]<=100) //把每种年龄的人里面排100名以后的人都去掉 
    		vv.push_back(v[i]);
    }
    while(m--){
    	printf("Case #%d:\n",++cnt);
    	scanf("%d%d%d",&k,&a,&b);
    	int num=0;
    	for(int i=0;i<vv.size();++i){
    		if(vv[i].b<a||vv[i].b>b) continue;
    		cout<<vv[i].a<<" ";
        	printf("%d %d\n",vv[i].b,vv[i].c);//注意!写成cout就超时 
        	num++;
        	if(num>=k) break;
    	}
    	if(num==0)
    		printf("None\n");  
    }
    return 0;   
}

https://www.patest.cn/contests/pat-a-practise/1103

#include<bits/stdc++.h> 
using namespace std; 
int x[205];
int path[1005];
int ans[1005];
int n,g,a,u,maxx;
void dfs(int s,int w){
	if(w==g){
		if(s==n){
			u=1;
			int sum=0;
			for(int i=0;i<w;++i)
				sum+=path[i];
			if(sum>=maxx){
				maxx=sum;
				for(int i=0;i<w;++i)
					ans[i]=path[i];
			}
		}
		return ;
	}
	int f=(w>0?path[w-1]:1); 
	for(int i=f;i<=20;++i){ //从1开始遍历就会超时(但是不理解为什么同样的逆序遍历会超时)
		if(s+x[i]>n) break;
		path[w]=i;
		dfs(s+x[i],w+1);
	}
}
int main(){	
	cin>>n>>g>>a;
	for(int j=1;j<=20;++j){
		x[j]=pow(j,a);
		if(x[j]>400) break;
	}
	dfs(0,0);
	if(u==0)
		cout<<"Impossible"<<endl;
	else{
		cout<<n<<" = ";
		for(int i=g-1;i>0;--i)
			cout<<ans[i]<<"^"<<a<<" + ";
		cout<<ans[0]<<"^"<<a<<endl;
	}
}

https://www.patest.cn/contests/pat-a-practise/1063

用map的超时代码:

#include<bits/stdc++.h> 
#define ll long long 
using namespace std;
int n,m,a,b;
vector<int> v[55];
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;++i){
		scanf("%d",&m);
		while(m--){
			scanf("%d",&a);
			v[i].push_back(a);
		}
	}
	scanf("%d",&m);
	while(m--){
		scanf("%d%d",&a,&b);
		a--;b--;
		map<int,int> r;
		int len=(int)v[a].size(); 
		for(int i=0;i<len;++i){
			r[v[a][i]]=1;
		}
		int tmp=r.size();
		len=(int)v[b].size(); 
		int s1=0,s2=0;
		for(int i=0;i<len;++i){
			if(r[v[b][i]]==1){
				r[v[b][i]]=-1;
				s1++;
			}
			else if(r[v[b][i]]==0){
				s2++;
				r[v[b][i]]=-1;
			}
		}
		s2+=tmp-s1;
		s2+=s1;
		s1*=100;
		printf("%.1f",(double)s1/s2);
		cout<<"%"<<endl;
	}
}
用set不超时,既有去重功能又有.count功能,这样只需要一个for就可解决:

#include<bits/stdc++.h> 
#define ll long long 
using namespace std;
int n,m,a,b;
set<int> v[55];
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;++i){
		scanf("%d",&m);
		while(m--){
			scanf("%d",&a);
			v[i].insert(a);
		}
	}
	scanf("%d",&m);
	while(m--){
		scanf("%d%d",&a,&b);
		a--;b--;
		int s1=0;
		for(set<int>::iterator it=v[a].begin();it!=v[a].end();++it){
			if(v[b].count(*it))
				s1++;
		}
		printf("%.1f",(double)s1*100/(v[a].size()+v[b].size()-s1));
		cout<<"%"<<endl;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值