A,B送分签到。
C的话暴力搞法直接排序,然后看看第k个数跟第k+1个数是不是一样就好了,但是一定要特判k=0||k=n的情况,wa了两发非常zz。当然想跑得更快可以二分搞搞。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int num[200005],n,k;
int check(int x)
{
int cnt=0;
for(int i=1;i<=n;i++)
if(num[i]<=x)
cnt++;
return cnt;
}
int main()
{
int k,i,j;
cin>>n>>k;
for(i=1;i<=n;i++)scanf("%d",&num[i]);
int left=1,right=1e9,mid;
while(left<=right){
mid=(left+right)>>1;
if((j=check(mid))>k){
right=mid-1;
}
else if(j==k){
cout<<mid<<endl;return 0;
}
else left=mid+1;
}
cout<<-1<<endl;
return 0;
}
D.
注意到这样一个事实:序列从左往右3这个因子的数量是不断变少的,2这个因子是不断变多的,所以是不可逆的变换,不会成环。那么总共100个数,其实可以直接拓扑排序搞一波。更巧妙的思路则是可以根据这个特点直接进行排序:首先按照数字中3的因数个数从大到小排序,因数个数相同时则按照2的个数从小到大排序即可。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
int main()
{
vector<int>G[105];int indegree[105]={0};
int n,i,j,k;
cin>>n;
ll num[105];
for(i=1;i<=n;i++)scanf("%lld",&num[i]);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(i==j)continue;
if(num[j]==num[i]*2||(num[i]%3==0&&num[j]==num[i]/3)){//一定要判断能否整除3!!
G[i].push_back(j);indegree[j]++;
}
}
queue<int>que;
for(i=1;i<=n;i++)if(indegree[i]==0)que.push(i);
int cnt=0;
while(!que.empty()){
i=que.front();que.pop();
cout << num[i] << ' ';
for (j = 0; j < G[i].size(); j++) {
k = G[i][j];
indegree[k]--;
if(!indegree[k])que.push(k);
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define LL long long
struct node{
LL a,b;
}A[110];
int cmp(node m,node n){
if(m.b==n.b)return m.a<n.a;
return m.b>n.b;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>A[i].a;
LL k=A[i].a;
while(k%3==0&&k){
A[i].b++;
k/=3;
}
}
sort(A+1,A+1+n,cmp);
for(int i=1;i<=n;i++)cout<<A[i].a<<" ";
}
E.
重点是注意题目描述,题目要求的是类似于一种完美的回路,没有非回路部分并且回路里面没有再回路,在这种情况下,一个点如果是回路中的一部分,当且仅当它恰好有两条边。那么我们全部扫过去dfs一遍即可。
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>G[200005];
bool vis[200005],iscircle;
void dfs(int x)
{
vis[x]=true;
if(G[x].size()!=2)iscircle=false;
for(auto a:G[x])
if(!vis[a])
dfs(a);
}
int main()
{
int n,m,i,j;
cin>>n>>m;
for(i=1;i<=m;i++) {
int a,b;
scanf("%d%d",&a,&b);
G[a].push_back(b);G[b].push_back(a);
}
int ans=0;
for(i=1;i<=n;i++){
if(!vis[i]){
iscircle=true;
dfs(i);
if(iscircle)ans++;
}
}
cout<<ans<<endl;
return 0;
}
F.
用dp的思想去做吧,从前往后扫一遍,拿一个map记录以当前数为结尾的最长上升子序列长度即可。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
int main()
{
map<int,int>m;//m记录的是第一个键值为结尾的最长连续上升子序列长度
int n,i,j,k,a[200005];
int maxn=0,maxnum;
cin>>n;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
j=m[a[i]]=m[a[i]-1]+1;
if(j>maxn)maxn=j,maxnum=a[i];
}
cout<<maxn<<endl;
j=maxnum-maxn+1;
for(i=1;maxn;i++){
if(a[i]==j){
printf("%d%c",i,maxn==1?'\n':' ');
maxn--;j++;
}
}
return 0;
}