【PAT】卡时专题

来源:互联网 发布:ss账号哪里购买好 知乎 编辑:程序博客网 时间:2024/05/01 21:04

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;}}


0 0