C题,就是给过题的时间和题目总数和排名,问是否可以唯一的确定一个合法序列。
首先如果时间都是0的话那么过题数都是0,否则就反着找,时间为0,就是0题,否则一开始就是一题,然后时间如果比前面的小就一样,大就加1,最后的题数和总题数一样就可以唯一确定。
#include<bits/stdc++.h> using namespace std; #define LL long long struct mp{ int n; vector<string>a; mp(){} }; vector<mp>p(105); bool cmp(mp p1,mp p2){ return p1.n<p2.n; } int main(){ int n,m; cin>>n>>m; vector<int>p;p.clear(); int flag=0; for(int i=0;i<n;i++){ int v;cin>>v; p.push_back(v); if(v!=0)flag=1; } if(flag==0){ for(int i=1;i<=n;i++)cout<<0<<endl; return 0; } int now=-1,min=0; vector<int>q; for(int i=p.size()-1;i>=0;i--){ if(p[i]==0){ now=0; } else{ if(min==0){ now=1;min=p[i]; } else{ if(p[i]<=min)min=p[i]; else { now++; min=p[i]; } } } q.push_back(now); } if(now==m){ for(int i=q.size()-1;i>=0;i--)cout<<q[i]<<endl; } else cout<<"ambiguous"<<endl; }
D题,0和1都不用考虑,对于其他的我们从最大的点开始搜索,然后一直先找最大的,最后可以找多少个就是答案。
#include<bits/stdc++.h> using namespace std; #define LL long long int a[505][505]; int vis[505][505]; int xx[4]={0,0,1,-1}; int yy[4]={1,-1,0,0}; int n,m; struct mp{ int x, y; int w; mp(int a,int b,int c){x=a;y=b;w=c;} }; bool cmp(mp p1,mp p2){ return p1.w>p2.w; } void solve(int x,int y,int nm){ if(vis[x][y]==1)return ; vis[x][y]=1; vector<mp>q; q.clear(); for(int i=0;i<4;i++){ int dx=x+xx[i]; int dy=y+yy[i]; if(dx>=1&&dx<=n&&dy>=1&&dy<=m&&vis[dx][dy]!=1&&a[dx][dy]!=0&&a[dx][dy]!=1){ q.push_back(mp(dx,dy,a[dx][dy])); } } sort(q.begin(),q.end(),cmp); for(int i=0;i<q.size();i++){ if(vis[q[i].x][q[i].y]==0&&nm>=q[i].w){ solve(q[i].x,q[i].y,q[i].w); } } } vector<mp>p; int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>a[i][j]; if(a[i][j]!=0&&a[i][j]!=1) p.push_back(mp(i,j,a[i][j])); } } sort(p.begin(),p.end(),cmp); int ans=0; for(int i=0;i<p.size();i++){ if(vis[p[i].x][p[i].y]==0){ //cout<<p[i].x<<" "<<p[i].y<<endl; solve(p[i].x,p[i].y,p[i].w); ans++; } } cout<<ans<<endl; }
F题,每个点都要有点和它连接,或者是本身就是个点,最小的是一个树的形状,添加一个0号点,把自身是发电站的费用看成0号点到那一个点的费用,就是最小生成树问题(find一定要更新数组)
#include<bits/stdc++.h> using namespace std; int s[200005]; int find(int x){ return s[x]==x?s[x]:s[x]=find(s[x]); } struct mp{ int x,y,w; mp(int a,int b,int c){ x=a;y=b;w=c; } }; vector<mp>p; bool cmp(mp p1,mp p2){ return p1.w<p2.w; } int main(){ int n,m; cin>>n>>m; p.clear(); for(int i=0;i<=n;i++)s[i]=i; for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); p.push_back(mp(0,a,b)); } for(int i=1;i<=n;i++){ int a; scanf("%d",&a); if(i==n){ p.push_back(mp(n,1,a)); } else p.push_back(mp(i,i+1,a)); } sort(p.begin(),p.end(),cmp); long long ans=0; for(int i=0;i<p.size();i++){ int a=find(p[i].x); int b=find(p[i].y); if(a!=b){ s[a]=b; ans+=p[i].w; } } cout<<ans<<endl; }
G找最多的种类,结构体排序
I题,设一条边为x+2 另一条边为y+2在根据a,b,c就可以推出是不是正确的
#include<bits/stdc++.h> using namespace std; #define LL long long struct mp{ int n; vector<string>a; mp(){} }; vector<mp>p(105); bool cmp(mp p1,mp p2){ return p1.n<p2.n; } int main(){ LL a,b,c; cin>>a>>b>>c; if(a!=4||b%2!=0){ cout<<"impossible"<<endl; return 0; } if((b*b/4-4*c)<0){ cout<<"impossible"<<endl; return 0; } LL x=(b/2+sqrt(b*b/4-4*c))/2; LL y=b/2-x; // cout<<x<<" "<<y<<endl; if(x*2+y*2==b&&x*y==c){ cout<<x+2<<" "<<y+2<<endl; } else{ cout<<"impossible"<<endl; } }