Codeforces Round #479 (Div. 3)(A-F)題解

Codeforces Round #479 (Div. 3)(A-F)題解

傳送門

A. Wrong Subtraction

思路:簽到題,根據題意模擬即可。

時間複雜度:O(k)O(k)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int main(){
	int n,k;
	scanf("%d%d",&n,&k);
	for(int i=1;i<=k;i++){
		if(n%10!=0) n--;
		else n/=10;
	}
	cout<<n<<endl;
	return 0;
}

B. Two-gram

思路:暴力,因爲所要求的子串長度爲22,所以可以枚舉長度爲2的字符串。

時間複雜度:O(262n)O(26^2n)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int a[26][26];
int main(){
	int n;
	cin>>n;
	string s;
	cin>>s;
	for(int i=0;i<n-1;i++){
		a[s[i]-'A'][s[i+1]-'A']++;
	}
	int mx=0,x,y;
	for(int i=0;i<26;i++)
		for(int j=0;j<26;j++){
			if(a[i][j]>mx){
				mx=a[i][j],x=i,y=j;
			}
		}
	printf("%c%c\n",x+'A',y+'A');
	return 0;
}

C. Less or Equal

思路:

我的解法:二分枚舉答案,即最大值最小化。時間複雜度:O(nlogn)O(nlogn)


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
int a[N],n,k;
int check(int x){
	int  p=upper_bound(a+1,a+n+1,x)-a;
	p--;
	return p;
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	int l=1,r=a[n];
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)>=k) r=mid-1;
		else l=mid+1;
	}
	if(check(l)!=k) puts("-1");
	else printf("%d\n",l); 
	return 0;
}

實際上是我想多了,沒必要這麼麻煩,直接排序選第kk小的數即可,注意特判數的範圍是否則屬於[1,1e9][1,1e9]
時間複雜度:O(n)O(n)
這裏就不放代碼了。

D. Divide by three, multiply by two

思路:貪心+排序,因爲只有兩種操作:除以33和乘以22,所以含因子3越多的個數要越靠前,又因爲有乘2的操作,所以當33的個數相同的時候,就取因子22越少的數即可。

時間複雜度:O(n(logn+log3n))O(n(logn+log_3n))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105+10,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
ll a[N];
pair<int,PII>b[N];
bool cmp(pair<int,PII> a,pair<int,PII> b){
	return a.se.se==b.se.se?a.se.fi<b.se.fi:a.se.se>b.se.se;
}
int main(){	
	int n; 
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		ll x=a[i];
		b[i].fi=i;
		for(int j=2;j<=3;j++)
			while(x%j==0){
				if(j==2) b[i].se.fi++;
				else b[i].se.se++;
				x/=j;
			}	
	}
	
	sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++)
		printf("%lld ",a[b[i].fi]);
	return 0;
}

E. Cyclic Components

題意:求給定無向圖的所有環(這裏的環是每個結點度數都爲2的環)個數。

思路:顯然使用dfsdfs,因爲題目不保證圖是連通的,所以用一個visvis標記結點是否被訪問過,可能需要多次dfsdfs,每次若遍歷到已經標記過的結點而且所有結點度數都爲22,則ans++ans++

時間複雜度:O(n+m)O(n+m)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first 
#define se second
vector<int>e[N];
int vis[N],d[N],ans,f;
void dfs(int u,int fa){
	for(auto v:e[u]){
		if(v==fa||d[v]!=2) continue;	
		//printf("%d->%d",u,v);
		if(!vis[v]&&d[v]==2) vis[v]=1,dfs(v,u);
		else if(vis[v]&&d[v]==2){
			if(!f)
			ans++,f=1;
			else return;
		}
	}
} 
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		e[u].push_back(v),e[v].push_back(u);
		d[u]++,d[v]++;
	} 
	for(int i=1;i<=n;i++){
		if(!vis[i]&&d[i]==2) f=0,vis[i]=1,dfs(i,-1);
	}
	printf("%d\n",ans);
	return 0;
}

F. Consecutive Subsequence

題意:求最長(連續遞增)子序列。

思路:這裏的連續遞增指得是子序列的數爲1,2,31,2,3的相連的數相差1的形式。

根據題目顯然考慮dpdp解決此題,我們可以子序列的末尾的數,即最大值xx爲下標,令dp[x]dp[x]表示以元素xx結尾的最大長度。

因爲a[i]1e9a[i]\leq 1e9,所以考慮離散化,用mapmap儲存。

dp[x]=(dp[x],dp[x1]+1)dp[x]=(dp[x],dp[x-1]+1)

因爲是順序遍歷,所以可以一邊輸入一遍更新dp[]dp[]

對於輸出下標,則可以找到起始點st=xdp[x]+1st=x-dp[x]+1.

然後順序掃一遍即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+100;
#define mst(a) memset(a,0,sizeof a)
int a[N];
map<int,int>mp;
int main(){
	int n;
	scanf("%d",&n);
	int ans=0;
    for(int i=1;i<=n;i++){
    	scanf("%d",&a[i]);
    	mp[a[i]]=mp[a[i]-1]+1;
    	if(mp[a[i]]>mp[ans]) ans=a[i];
	}
	printf("%d\n",mp[ans]);
	int st=ans-mp[ans]+1;
	for(int i=1;i<=n;i++)
		if(a[i]==st) printf("%d ",i),st++;
	return 0;
} 

ps:ps:此題有個坑點是用unordered_mapunordered\_mapTLETLE ,大概是哈希表建立的時間耗費較長?,不知道希望有人能說說。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章