刚开场卡了一会,凭借手速切出了前三题,,然后开始挂机。
D:点击打开链接
题意:给你n个数,这n个数是由每个数的前一个数*2,/3得到的(注意不是随机的,是按照一次乘2一次除3)。但是给你的这n个数是打乱的,要求恢复原本的顺序。
input
Copy
6 4 8 6 3 12 9
output
Copy
9 3 6 12 4 8
思路一:全排列,然后判断。 打了一遍玩玩,最长100个数,100!,,复杂度耗不起。
思路二:找规律,想先找最小的和最大的,然后递推(没做出来)
思路三:参考别人的题解,每一个数都可以计算出它包含多少个因子2,多少个因子3。然后利用结构体排个序,很容易就可以得到结果。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 105; ll n,nn,k; struct node{ ll two,three,num; bool operator<(const node &p)const { if(three==p.three) return two<p.two; return three>p.three; } }a[maxn]; int main() { cin>>nn; n = nn; int cnt = 0; while(n--) { node q; cin>>k; q.num = k; int x=0,y=0; while(k%3==0) { k /= 3; x++; } while(k%2==0) { k /= 2; y++; } q.two = y; q.three = x; a[cnt++] = q; } sort(a,a+cnt); for(int i=0;i<cnt;i++) cout<<a[i].num<<" "; cout<<endl; return 0; }
第五题:点击打开链接
求有几个纯环(没有多余的边)。
思路:dfs,如果是纯环,那么一个节点有且只有2条边,其余看代码。
#include<bits/stdc++.h> using namespace std; const int maxn = 200005; int n,m,ans; vector<int>E[maxn]; bool vis[maxn],flag; void dfs(int x) { if(E[x].size()!=2) flag = false; for(int i=0;i<E[x].size();i++) { if(!vis[E[x][i]]) { vis[E[x][i]] = 1; dfs(E[x][i]); } } } int main() { cin>>n>>m; for(int i=0;i<m;i++) { int x,y; cin>>x>>y; E[x].push_back(y); E[y].push_back(x); } for(int i=1;i<=n;i++) { //memset(vis,0,sizeof(vis)); if(!vis[i]) { flag = 1; dfs(i); if(flag) ans++; } } cout<<ans<<endl; return 0; }
F题:点击打开链接
题目大意:输入n个数,求最大连续上升子序列(要记录序号)
真的是脑抽了,第一想法n^2dp,字符串瞎操作,果断TLE。。
#include<bits/stdc++.h> #include<string> using namespace std; const int maxn = 200005; typedef long long ll; int n,ans,tot=0,pos; ll a[maxn]; bool flag[maxn]; string s,sn; int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lld",&a[i]); } ans = 0; for(int i=0;i<n;i++) { if(flag[i]) continue; flag[i] = 1; pos = a[i]; tot = 1; sn.clear(); string temp; stringstream ss; ss<<i+1; ss>>temp; sn += temp; for(int j=i;j<n;j++) { if(n-j+tot<ans) break; if(a[j]==pos+1) { tot++; pos = a[j]; string temp; stringstream ss; ss<<j+1; ss>>temp; sn += temp; } } if(tot>ans) { ans = tot; s = sn; } } cout<<ans<<endl; for(int i=0;i<s.length();i++) cout<<s[i]<<" "; return 0; }
然后参考别人做法,O(nlogn)的,用了map维护的DP。
#include<bits/stdc++.h> using namespace std; const int maxn = 200005; int n,a[maxn],pos,maxi=-1; map<int,int> dp; int main() { cin>>n; for(int i=0;i<n;i++) scanf("%d",&a[i]); for(int i=n-1;i>=0;i--) { dp[a[i]] = max(dp[a[i]],dp[a[i]+1]+1); if(dp[a[i]]>maxi) { maxi = dp[a[i]]; pos = a[i]; } } cout<<maxi<<endl; for(int i=0;i<n;i++) { if(a[i]==pos) { cout<<i+1<<" "; pos++; } } cout<<endl; return 0; }这场DIV3总体来说还是比较简单的,但我菜,需努力。