codeforces Gym - 101341

48 篇文章 0 订阅
34 篇文章 0 订阅

B - Pursuing the Happiness

题目链接

题意

给定一串字符串,问能否交换两个位置的字符使这个字符串中找不到"happiness"

思路

stirng.find查找"happiness"位置,若有返回位置pos,反之返回-1
有三种情况:

  • 1.原串中开始时不存在"happiness",从头到尾遍历,交换相邻两个位置的字符串,看交换后的字符串是否存在"happiness",输出位置,结束程序
  • 2.原串中存在1个"happiness",交换pos+1和pos+2位置处的字符,看是否存在"happiness"
  • 3.原串中存在多个"happiness",查找第二个"happiness"所在位置为ppos,交换pos+1与ppos+2处字符串,看是否存在"happiness"

注意:输出位置要+1(Positions in the string are numbered from one.)

答案

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

string s;
string str;

int main()
{
    cin>>s;
    str.assign("happiness");
//    int cnt=0;
    if((int)s.find(str)==-1){
        for(int i=0;i<(int)s.size();i++){
            swap(s[i],s[i+1]);
            if((int)s.find(str)==-1){
                cout<<"YES"<<endl;
                cout<<i+1<<" "<<i+2<<endl;
                return 0;
            }
            swap(s[i],s[i+1]);
        }
    }
    else{
        int pos=(int)s.find(str);
        int ppos=(int)s.find(str,pos+1);
        if(ppos!=-1){
           swap(s[pos+1],s[ppos+2]);
           if((int)s.find(str)==-1){
                cout<<"YES"<<endl;
                cout<<pos+2<<" "<<ppos+3<<endl;
                return 0;
           }
        }
        else{
            swap(s[pos],s[pos+1]);
            if((int)s.find(str)==-1){
                cout<<"YES"<<endl;
                cout<<pos+1<<" "<<pos+2<<endl;
                return 0;
            }
        }
    }
    cout<<"NO"<<endl;
//    cout<<(int)s.find(str)<<endl;
    return 0;
}

C - Urn with Balls

题目链接

题意

有a个红球,b个绿球,c个未知颜色的球,最多取n个红球,m个绿球,问在符合条件的情况下最多取多少个球

思路

在判断过程中我们可以将c个球完全变为红球或者绿球来比较,sum=a+b+c为球的总数,如果a+c个红球大于n,则sum=min(sum,n);如果b+c个红球大于m,则sum=min(sum,m),sum即为所求数量

答案

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

int main()
{
    ll a,b,c;
    cin>>a>>b>>c;
    ll n,m;
    cin>>n>>m;
    ll sum=a+b+c;
    if(n<a+c) sum=min(sum,n);
    if(m<b+c) sum=min(sum,m);
    cout<<sum<<endl;
    return 0;
}

D - Jumps

题目链接

题意

在数轴上,给定n个可移动的距离,问通过这些可移动距离的无限次组合能否到达给定的x

思路

求这n个距离的gcd,所求gcd即为可以移动的最小的单位长度,若x能整除gcd则可到达,反之,无法到达。

答案

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

ll a[N];

int main()
{
    ll n,x;
    cin>>n>>x;
    for(ll i=1;i<=n;i++){
        cin>>a[i];
    }
    ll gcd=a[1];
    for(ll i=2;i<=n;i++){
        gcd=__gcd(gcd,a[i]);
    }
    x=abs(x);
    if(x%gcd==0) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

E - Bonuses and Teleports

题意

给出 N 个跳点和 M 个目标点,跳点之间可任意传送,问从第一跳点开始,走遍所有目标点并返回第一跳点的最小 cost 是多少?

思路

见代码

答案

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x7fffffff
#define PI acos(-1)
#define eps 1e-7
const int mod =  1e9 + 7;
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

ll a[N];
ll b[N];
ll c[N];
ll d[N];

int main()
{
    int n,m;
    cin>>n>>m;
    a[0]=-INF;
    a[n+1]=INF;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    b[0]=b[m+1]=a[1];
    for(int i=1,j=0;i<=m;i++){
        while(a[j+1]<=b[i]) j++;
        if(j>0) c[i]=b[i]-a[j];
        else c[i]=INF;
        if(j<n) d[i]=a[j+1]-b[i];
        else d[i]=INF;
        c[i]=min(c[i],d[i]);
    }
    ll ans=0;
    c[0]=c[m+1]=0;
    for(int i=1;i<=m+1;i++){
        ll t=abs(b[i-1]-b[i]);
        t=min(t,c[i-1]+c[i]);
        ans+=t;
    }
    cout<<ans<<endl;
    return 0;
}

G - I love Codeforces

题目链接

题意

给你n个字符串,以及m个喜欢关系,如果u喜欢v,这时候u会把它的用户名改为 I_love_ 加上v当时的用户名

思路

模拟题,纯模拟会出MLE,RE,TLE等锅,只需要记录每个点喜欢(I_love_)的个数,以及每个点对应的最后一个点。

答案

法一:

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

string s[N];
vector<pair<int,int> > vp;

int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>s[i];
    }
    //pair<int,int> pp;
    int m;
    cin>>m;
    int u,v;
    for(int i=0;i<m;i++){
        cin>>u>>v;
        u--,v--;
//        vp[i].first=u;
//        vp[i].second=v;
        vp.push_back({u,v});
    }
    int cnt=0;
    int next=0;
    for(int i=(int)vp.size()-1;i>=0;i--){
        if(vp[i].first==next){
            cnt++;
            next=vp[i].second;
        }
    }
    for(int i=0;i<cnt;i++){
        cout<<"I_love_";
    }
    cout<<s[next]<<endl;
    return 0;
}

法二

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

struct node{
    string name;
    int sum;
}dp[N];

int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>dp[i].name;
        dp[i].sum=0;
    }
    int m;
    cin>>m;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        dp[u].name.assign(dp[v].name);
        dp[u].sum=dp[v].sum+1;
    }
    while(dp[1].sum--) cout<<"I_love_";
    cout<<dp[1].name<<endl;
    return 0;
}

H - Perfect Ban

题目链接

题意

随意删除一行一列,使矩阵剩下元素中的最大值是所有删除情况的最小情况。

思路

(这是别人的描述,感觉他比我说的清楚:-) )
根据贪心的思想,我们所删除的行和列应该是尽可能的包含可能多的大数,我们首先确定矩阵最大元素所在的行和列,那这个最大值我们是一定要删除的,所以下一个要寻找的应该是分别除去最大值所在行 列的次大值(如果只单纯的除去最大值找次大值的话,会忽略一种情况,就是我们的次大值和最大值在同一行同一列的情况,这样的话,我们必然是要删除最大值的行或者列的,这个次大值就没有了意义,偷偷告诉大家,这种情况就是这个题的样例8哦,我可是wa了好多发呢,qwq),我们找到次大值之后, 我们肯定是要删除的是(最大值的行,次大值的列) 或者 (次大值的行,最大值的列) 这其中的一种情况的, 那我们怎么判断删除哪种呢, 我们就可以非常直接的暴力跑这两种情况中矩阵剩下的元素哪种情况的小

答案:

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 1e6 + 10;
const int M = 1111;
using namespace std;

struct node{
    int x;
    int y;
    int data;
}dp[N];

int a[M][M];

bool cmp(node x,node y){
    return x.data>y.data;
}

int main()
{
    int n,m;
    cin>>n>>m;
    int cnt=n*m;
    for(int i=0;i<cnt;i++){
        cin>>dp[i].data;
        dp[i].x=i/m;
        dp[i].y=i%m;
        a[i/m][i%m]=dp[i].data;
    }
    sort(dp,dp+cnt,cmp);
    int pos=0;
    int x1=dp[pos].x;
    int y1=dp[pos++].y;
    int x2=dp[pos].x;
    int y2=dp[pos++].y;
    int x3=dp[pos].x;
    int y3=dp[pos++].y;
    if(x2!=x1&&y2!=y1){
        if(x3==x1||y3==y2) cout<<x1+1<<" "<<y2+1<<endl;
        else if(x3==x2||y3==y1) cout<<x2+1<<" "<<y1+1<<endl;
        else cout<<x1+1<<" "<<y2+1<<endl;
    }
    else if(x2==x1){
        if(x3!=x1) cout<<x1+1<<" "<<y3+1<<endl;
        else{
            while(dp[pos].x==x3){
                pos++;
            }
            cout<<x1+1<<" "<<dp[pos].y+1<<endl;
        }
    }
    else{
        if(y3!=y1) cout<<x3+1<<" "<<y1+1<<endl;
        else{
            while(dp[pos].y==y3){
                pos++;
            }
            cout<<dp[pos].x+1<<" "<<y1+1<<endl;
        }
    }
    return 0;
}

M - Last Man Standing

题目链接

题意

给你n个人,然后给你一个非递减序列a1 a2 an 分别表示每个人击杀人数,要求满足游戏规则输出YES并且输出每个人击杀的玩家序号,否则输出No.

思路

贪心,靠后的人尽量杀更靠后的人。
即将数组从后往前扫,对于每一个人i,都被此时最靠后的杀人数不为0的人杀,并且杀人的人杀人数减1。
判断不成立的条件是杀人总数大于等于总人数。

答案

#include <iostream>
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-4
const int N = 2e5 + 10;
const int M = 111;
using namespace std;

ll a[N];

int main()
{
    ll n;
    cin>>n;
    ll sum=0;
    for(ll i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    if(n==1){
        if(!a[1]) puts("YES");
        else puts("NO");
    }
    else{
        if(sum>=n) puts("NO");
        else{
            puts("YES");
            int pos;
            for(int i=n;i>=1;i--){
                if(a[i]){
                    pos=i;
                    break;
                }
            }
            while(a[pos]&&n!=1){
                if(!a[n]){
                    cout<<pos<<" "<<n<<endl;
                    a[pos]--;
                    if(!a[pos]) pos--;
                    if(!a[n]) n--;
                }
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CodeForces - 616D是一个关于找到一个序列中最长的第k好子段的起始位置和结束位置的问题。给定一个长度为n的序列和一个整数k,需要找到一个子段,该子段中不超过k个不同的数字。题目要求输出这个序列最长的第k好子段的起始位置和终止位置。 解决这个问题的方法有两种。第一种方法是使用尺取算法,通过维护一个滑动窗口来记录\[l,r\]中不同数的个数。每次如果这个数小于k,就将r向右移动一位;如果已经大于k,则将l向右移动一位,直到个数不大于k。每次更新完r之后,判断r-l+1是否比已有答案更优来更新答案。这种方法的时间复杂度为O(n)。 第二种方法是使用枚举r和双指针的方法。通过维护一个最小的l,满足\[l,r\]最多只有k种数。使用一个map来判断数的种类。遍历序列,如果当前数字在map中不存在,则将种类数sum加一;如果sum大于k,则将l向右移动一位,直到sum不大于k。每次更新完r之后,判断i-l+1是否大于等于y-x+1来更新答案。这种方法的时间复杂度为O(n)。 以上是两种解决CodeForces - 616D问题的方法。具体的代码实现可以参考引用\[1\]和引用\[2\]中的代码。 #### 引用[.reference_title] - *1* [CodeForces 616 D. Longest k-Good Segment(尺取)](https://blog.csdn.net/V5ZSQ/article/details/50750827)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces616 D. Longest k-Good Segment(双指针+map)](https://blog.csdn.net/weixin_44178736/article/details/114328999)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值