赞
踩
看群友在水这个比赛玩玩,于是也去打了一下重现赛。
事实证明,群友轻松AK,而我只会暴力。
总的难度就是PAT甲的难度吧,数据很不错,恶心的一批。
补题完结
方法一: 自己的傻叉做法 预处理所有的4个数的平均值。用double 注意精度
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m; double a[N],b[N]; map<double,int>mp; int main(void) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%lf",&a[i]); for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { for(int k=j+1;k<n;k++) { for(int z=k+1;z<n;z++) { int temp=a[i]+a[j]+a[k]+a[z]; mp[temp/4.0]++; } } } } while(m--) { int t; scanf("%d",&t); bool flag=1; for(int i=0;i<t;i++) { scanf("%lf",&b[i]); if(!mp[b[i]]) flag=false; } if(flag) puts("Yes"); else puts("No"); } return 0; }
方法二: 只需处理所有的四个数的和即可,不用求平均
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m; int a[N],b[N]; map<int,int>mp; int main(void) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { for(int k=j+1;k<n;k++) { for(int z=k+1;z<n;z++) { int temp=a[i]+a[j]+a[k]+a[z]; mp[temp]++; } } } } while(m--) { int t; scanf("%d",&t); bool flag=1; for(int i=0;i<t;i++) { scanf("%d",&b[i]); if(!mp[b[i]*4]) flag=false; } if(flag) puts("Yes"); else puts("No"); } return 0; }
大木棋会打倒这个方向上离哲哲最近的 k 个小木棋
读了半天的假题。
1 1 1
2 2 2
3 3 1
步数为3 先打1再2再3
#include<bits/stdc++.h> using namespace std; typedef long long LL; LL ans,n,cnt; LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;} map<pair<LL,LL>,vector< pair<LL,LL> > >mp;//斜率映射到对应的距离加分数 int main(void) { cin>>n; for(int i=1;i<=n;i++) { LL x,y,c; cin>>x>>y>>c; ans+=c; LL temp=gcd(abs(x),abs(y)); mp[{x/temp,y/temp}].push_back({x*x+y*y,c}); //注意: 距离必须是x*x+y*y 单独的x是不行的因为还有y轴上的点 } cnt=0; for(auto i=mp.begin();i!=mp.end();i++)//枚举所有的方向 { auto ve=i->second; sort(ve.begin(),ve.end());//距离排序 for(int j=0;j<ve.size();j++) { if(ve[j].second!=1) { cnt++; if(j-1>=0&&ve[j-1].second==1) cnt++; } } if(ve[ve.size()-1].second==1) cnt++; } cout<<ans<<" "<<cnt; return 0; }
写的可以过,不过有点太卡时间。
#pragma GCC optimize(3) #include<bits/stdc++.h> using namespace std; const int N=1e3+10; int n,m,t,x; int g[N][N],dist[N],st[N]; int startx,maxv=1e9; int p[N][N]; map<int,int>val,ans;//val存的是该点最大的价值,ans存路径 void Dijkstra(int x) { memset(dist,0x3f,sizeof dist); memset(st,0,sizeof st); dist[x]=0; for(int i=0;i<n;i++) { int t=-1; for(int j=1;j<=n;j++) if(!st[j]&&(t==-1 || dist[j]<dist[t] )) t=j; st[t]=1; for(int j=1;j<=n;j++) { if(dist[j]>dist[t]+g[t][j]) { dist[j]=dist[t]+g[t][j]; val[j]=val[t]+p[t][j]; ans[j]=t; } else if(dist[j]==dist[t]+g[t][j]) { if(val[j]<val[t]+p[t][j]) { val[j]=val[t]+p[t][j]; ans[j]=t; } } } } int temp=0; for(int i=1;i<=n;i++) temp=max(temp,dist[i]); if(temp<maxv) maxv=temp,startx=x; } int main(void) { memset(g,0x3f,sizeof g); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); g[a][b]=g[b][a]=c; p[a][b]=d,p[b][a]=d; } for(int i=1;i<=n;i++) Dijkstra(i);//每一个点跑一下最短路,找到最短路中最大的值,最小的值 printf("%d\n",startx); val.clear(),ans.clear(); Dijkstra(startx); scanf("%d",&t); while(t--) { int x; scanf("%d",&x); int node=x; vector<int>path; while(node) { path.push_back(node); node=ans[node]; } for(int i=path.size()-1;i>=0;i--) { if(i!=path.size()-1) printf("->"); printf("%d",path[i]); } printf("\n%d %d\n",dist[x],val[x]); } return 0; }
很轻松的暴力做法骗22分
#include<bits/stdc++.h> using namespace std; const int N=1e5*3+10; int h[N],e[N],ne[N],idx; int st[N],vis[N]; int n,m,t; int startx,endx; bool flag; void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++;} void dfs(int u) { st[u]=1; if(u==endx&&!vis[u]) { flag=1; return; } for(int i=h[u];i!=-1;i=ne[i]) { int j=e[i]; if(!st[j]&&!vis[j]) dfs(j); } } int main(void) { memset(h,-1,sizeof h); cin>>n>>m>>t; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; add(a,b),add(b,a); } while(t--) { int c,q; cin>>c>>q; vis[c]=1; int ans=q; for(int i=0;i<q;i++) { memset(st,0,sizeof st); flag=0; cin>>startx>>endx; if(!vis[startx])dfs(startx); if(flag) ans--; } cout<<ans<<endl; } return 0; }
正解: 考虑将所有操作离线,逆序处理。即,先删除要删除的所有点,再倒着往里加点,顺便把询问处理掉,用并查集维护即可
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; typedef pair<int,int> PII; vector<int>ve[N];//存边 vector<PII>vis[N]; int p[N],s[N],ans[N]; int n,m,t; int find(int x) { if(x!=p[x]) p[x]=find(p[x]); return p[x]; } int main(void) { cin>>n>>m>>t; for(int i=1;i<=n;i++) p[i]=i; for(int i=1;i<=m;i++) { int a,b; cin>>a>>b; ve[a].push_back(b) ; ve[b].push_back(a); } for(int i=1;i<=t;i++) { int k,a,b; cin>>s[i]>>k; p[s[i]]=0;//标记为坏的 while(k--) { cin>>a>>b; vis[i].push_back({a,b}); } } for(int i=1;i<=n;i++) { if(p[i]) { for(int j=0;j<ve[i].size();j++) { if(p[ve[i][j]]) p[find(i)]=find(ve[i][j]); } } } for(int i=t;i;i--) { for(int j=0;j<vis[i].size();j++)//查询 { int fa=find(vis[i][j].first); int fb=find(vis[i][j].second); if(fa!=fb || fa==0 ) ans[i]++; } int k=s[i]; p[k]=k;//添加点 for(int j=0;j<ve[k].size();j++)//并查集处理 { if(p[ve[k][j]]) p[find(k)]=find(ve[k][j]); } } for(int i=1;i<=t;i++) cout<<ans[i]<<endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。