Codeforces Round #479 (Div. 3)(A-F)题解
A. Wrong Subtraction
思路:签到题,根据题意模拟即可。
时间复杂度:
#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
思路:暴力,因为所要求的子串长度为,所以可以枚举长度为2的字符串。
时间复杂度:
#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
思路:
我的解法:二分枚举答案,即最大值最小化。时间复杂度:
#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;
}
实际上是我想多了,没必要这么麻烦,直接排序选第小的数即可,注意特判数的范围是否则属于。
时间复杂度: 。
这里就不放代码了。
D. Divide by three, multiply by two
思路:贪心+排序,因为只有两种操作:除以和乘以,所以含因子3越多的个数要越靠前,又因为有乘2的操作,所以当的个数相同的时候,就取因子越少的数即可。
时间复杂度:
#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的环)个数。
思路:显然使用,因为题目不保证图是连通的,所以用一个标记结点是否被访问过,可能需要多次,每次若遍历到已经标记过的结点而且所有结点度数都为,则。
时间复杂度:
#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的形式。
根据题目显然考虑解决此题,我们可以子序列的末尾的数,即最大值为下标,令表示以元素结尾的最大长度。
因为,所以考虑离散化,用储存。
即。
因为是顺序遍历,所以可以一边输入一遍更新。
对于输出下标,则可以找到起始点.
然后顺序扫一遍即可。
#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;
}
此题有个坑点是用会 ,大概是哈希表建立的时间耗费较长?,不知道希望有人能说说。