【浮*光】【Codeforces Round #479 (Div. 3)】解题报告

一次边吃饭边写的题的神奇故事...

A. Wrong Subtraction  

传送门:http://codeforces.com/contest/977/problem/A

#include <cmath>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
/*Tanya通过以下算法:
    如果该号码的最后一位数字不为零,则将该号码减1;
    如果该数字的最后一位数字为零,她将该数字除以10。
给你一个整数n。进行k次减法的答案。  */
int main(){
	int n,k; cin>>n>>k;
	for(int i=1;i<=k;i++){
		if(n%10==0) n/=10;
		else n-=1;
	}
	printf("%d\n",n);
	return 0;
}

B. Two-gram 

传送门:http://codeforces.com/contest/977/problem/B

#include <cmath>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
using namespace std;
/* ss是一个有序对(即长度为二的字符串)的大写拉丁字母。 
例如,“AZ”,“AA”,“ZA” 。给你一个字符串s,由n个大写拉丁字母组成。 
查找给定字符串中包含的任何ss字符作为子字符串(即字符串的两个连续字符)的最大次数。 
例如,对于字符串s =“BBAABBBA”,答案是ss串“BB”,其包含在s中三次
请注意,ss的出现可以相互重叠。 */
const int MAXN = 1e5 + 10;
inline int read() { //读入优化
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
    return x * f;
} 
char s[MAXN]; string ss[MAXN];//字符串集合
int main(){
    int N=read(); scanf("%s",s+1);//从1开始
    for(int i = 1; i <= N - 1; i++)
        ss[i] += s[i], ss[i] += s[i + 1];//连续两个组成ss
    int mx = 0; string anss;
    for(int i = 1; i <= N - 1; i++) {
        int now = 0;
        for(int j = 1; j <= N - 1; j++)
            if(ss[i] == ss[j]) now++;
        if(now>mx) mx=now,anss=ss[i];//更新答案为now
    }
    cout<<anss<<endl;
    return 0;
}

C. Less or Equal  

传送门:http://codeforces.com/contest/977/problem/C

#include <cmath>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
/* 给一个整数序列,是否找到一个数x,(正好只有)k个数字<=x,找到输出x,
不能则输出-1。看第二组数据,要找到两个数字,排序后出现1,3,3,
会出现三个(>2)数字小于等于3,所以不能找到。注意,k=0的时候需要分类讨论,
k=0,a[1]!=1,输出-1;k=0其他情况,输出1即可。
分析》排序,判断k位置和k+1位置的数是否相等。特判k=0,a[1]=1的情况。   */
const int MAXN=1e6+10;
inline int read() { //读入优化
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
    return x * f;
} 
int n,k,a[MAXN];
int main(){
	n=read(); k=read(); 
    for(int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    if((a[k]==a[k+1])||(k>n)||(k==0&&a[1]==1)) puts("-1");
    else if(k==0) printf("1");
    else printf("%d",a[k]);//直接输出a[k]即可
    return 0;
}

D. Divide by three, multiply by two 

传送门:http://codeforces.com/contest/977/problem/D

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
/* D:4 8 6 3 12 9 把这个序列排成一个这样的序列, 
      前一位是后一位数的一半或者3倍,即9 3 6 12 4 8
题解:直接按对3有更多约数的多少来排(前一位是后一位的3倍),
     有相同个则从小到大(也就是前一位是后一位数的一半)  */
int num3(ll x){
    ll len = 0;
    while (x % 3 == 0 && x){
        x /= 3; len++;
    }
    return len;
}
bool cmp(ll a, ll b){
    if(num3(a)!=num3(b)) return num3(a)>num3(b);
    else return a<b;
}
ll a[110];
int main(){
    int n; scanf("%d", &n);
    for(int i=0;i<n;i++) cin>>a[i];
    sort(a,a+n,cmp);//按照题目要求的顺序排序
    for(int i=0;i<n;i++){
        cout<<a[i]; printf("%c",i==n-1?'\n':' ');
    } 
    return 0;
}

E. Cyclic Components 

传送门:http://codeforces.com/contest/977/problem/E

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;
/* E. Cyclic Components
题意简化: 给定点的个数和各条边,问有多少个环  
分析:环-> 一个点对应两次,使用并查集  */

const int maxn=2e5+10;
int pre[maxn],edg[maxn],cnt;
struct node{
    int x,y;
}a[maxn];

int ffind(int x){//并查集找相连
    if(x==pre[x])  return x;
    return pre[x]=ffind(pre[x]);
}

void join(int x,int y){//合并集合
    x=ffind(x),y=ffind(y);
    if(x!=y)  pre[x]=y;
    else cnt++;//环
}

int main(){
    int m,n; while(cin>>m>>n){
        for(int i=0;i<maxn;i++) pre[i]=i;
        memset(edg,0,sizeof(edg));
        for(int i=0;i<n;i++){
            cin>>a[i].x>>a[i].y;
            edg[a[i].x]++; edg[a[i].y]++;
        }
        cnt=0;
        for(int i=0;i<m;i++){
            if(edg[a[i].x]==2&&edg[a[i].y]==2)
                join(a[i].x,a[i].y);
        }
        cout<<cnt<<endl;
    }
    return 0;
}


F. Consecutive Subsequence

传送门:http://codeforces.com/contest/977/problem/F

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;

/* F》在数组中找出最长的递增子序列的长度以及下标位置。
样例》3 3 4 7 5 6 8 最长的子序列为3 4 5 6,下标为1 3 5 6或2 3 5 6。
题解》用map进行dp,mp[i]表示以i数字开头的最长的递增子序列的长度,
转移方程mp[i]=max(mp[i],mp[i-1]+1)
最后找出map里面子序列长度最长的数字i,倒着输出就行了。  */

const int maxn=2e5+10;
int a[maxn];
int main(){
    ios::sync_with_stdio(false);
    int n,tmp;
    while(cin>>n){
        map<int,int>mp;
        int max_pos=-1,Max=-1;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            mp[a[i]]=mp[a[i]-1]+1;
            if(mp[a[i]]>Max) Max=mp[a[i]],tmp=a[i],max_pos=i;
        }
        int u=tmp-Max+1;
        cout<<Max<<endl;
        bool f=true;
        for(int i=1;i<=max_pos;i++){
            if(a[i]==u){
                if(f) cout<<i,f=false;
                else cout<<" "<<i;
                u++;
            }
        }
        cout<<endl;
    }
    return 0;
}  //此题代码来自某位dalao qwq
                                                                            
                                                                                ——时间划过风的轨迹,那个少年,还在等你。

猜你喜欢

转载自blog.csdn.net/flora715/article/details/80381522