CodeForces1399总结

昨晚状态不怎么好,虽然前两个题做的还挺快(主要是太水了),第三个题就卡住了,一直在想怎么用技巧解决,想了好半天也没想到技巧,后来想着就暴力试一下吧,结果第一遍暴力忘记了一个步骤,脑子里想的挺好结果上去就WA,好几次提交才过了,第四个题也是一直觉得思路没错,一直WA,然后眼睁睁看着比赛结束了,很难受,这场比赛一直在犯马虎。我记得以前做题基本都一遍过,最近不知道咋了,老是出错,很烦躁。昨晚立的flag也破了,掉了十来分,不过知道自己错在哪里了就好,慢慢长经验(佛系)

A. Remove Smallest

给你n个数,若某两个数绝对值之差小于1,则可以去除其中一个,问最终能否只剩一个数。水题,排序后看是否有绝对值之差大于1的两个数即可

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=200005;
typedef long long ll;
ll t,a[55],n,i,j,k,ans,cnt,Max,Min;
int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        for(i=2;i<=n;i++)
        {
            if(a[i]-a[i-1]>1) break;
        }
        if(i==n+1)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
}

B. Gifts Fixing

给你两组数a,b,两组数的个数均为n,现在要使两组数分别相等(a中全部相等且b中全部相等),每次可以让其中一个a-1或其中一个b-1或对应的二者都减一,问至少多少次能使两组数分别相等。水题,看每组中的最小值,直接相加二者与最小值的差中较大的那个值即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=55;
typedef long long ll;
ll t,a[maxn],b[maxn],n,i,j,k,ans,cnt,sum,Max,Min1,Min2,Min;
int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n;
        Min1=INF;
        Min2=INF;
        sum=0;
        for(i=1; i<=n; i++)
        {
            cin>>a[i];
            Min1=min(Min1,a[i]);
        }
        for(i=1; i<=n; i++)
        {
            cin>>b[i];
            Min2=min(Min2,b[i]);
        }
        for(i=1;i<=n;i++)
        {
            sum+=max(a[i]-Min1,b[i]-Min2);
        }
        cout<<sum<<endl;
    }
}

C. Boats Competition

n个人参加龙舟比赛,每两人组队,二者质量之和必须相等,问最多能组成多少队。我直接暴力过的,没啥说法了。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=55;
typedef long long ll;
ll t,a[maxn],b[2*maxn],w,n,i,j,k,ans,cnt,sum,index,Max,Min1,Min2,Min;
int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=1; i<=n; i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        Max=0;
        for(i=1; i<=n; i++)
        {
            for(j=n; j>i; j--)
            {
                sum=0;
                index=a[i]+a[j];
                ans=j;
                cnt=i;
                while(cnt<ans)
                {
                    if(a[cnt]+a[ans]==index)
                    {
                        sum++;
                        cnt++;
                        ans--;
                    }
                    else if(a[cnt]+a[ans]<index)
                    {
                        cnt++;
                    }
                    else if(a[cnt]+a[ans]>index)
                    {
                        ans--;
                    }
                }
                Max=max(Max,sum);
            }
        }
        cout<<Max<<endl;
    }
}

D. Binary String To Subsequences

给你一串二进制字符串,从中挑出最少的子串,使得子串的0和1均不相邻。问最少的子串数量是多少。我刚开始想的是只需要看连续的0或者1即可,找出最长连续的数字的长度,不连续的地方输出1,连续的地方就累加输出,后来发现假设输入00100,我代码的输出是12112,显然思路就不对了,答案应该是12223,至少需要三个子串。当时就这个地方没想透,然后一直WA。下面是代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=200005;
typedef long long ll;
int t,a[maxn],w,n,i,j,k,ans,cnt,sum,index,Max,Min1,Min2,Min;
char s[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        k=0;
        sum=0;
        cin>>n;
        cin>>s;
        queue<int> q1,q0;
        for(i=0;i<n;i++)
        {
            if(s[i]=='0')
            {
                if(q0.size()!=0)
                {
                    int x=q0.front();
                    q0.pop();
                    a[i]=a[x];
                    q1.push(i);
                }
                else
                {
                    a[i]=++sum;
                    q1.push(i);
                }
            }
            else
            {
                if(q1.size()!=0)
                {
                    int x=q1.front();
                    q1.pop();
                    a[i]=a[x];
                    q0.push(i);
                }
                else
                {
                    a[i]=++sum;
                    q0.push(i);
                }
            }
        }
        cout<<sum<<endl;
        for(int i=0;i<n;i++)
            cout<<a[i]<<" ";
        cout<<endl;
    }
    return 0;
}

E1. Weights Division (easy version)

如果我没理解错的话,应该是一个无向连通图,每条边都有一个权值,路径的权值是该路径上边权值的总和。从顶点到自身的路径权值为0,每次移动,你都可以选择一条边并将其权值整除2。题目要求找出使从根到每个叶的路径的权值之和最多为S所需的最小移动次数。

E2. Weights Division (hard version)

与E1类似,但是所求的东西不同,E2要求求出最小权值和,使从根到每个叶的路径的权值之和最小。

F. Yet Another Segments Subset

给你n个线段的始末坐标,你需要从给出的线段集的选出最多的线段数组成其子集,子集要么每两个线段不相交,要么一个包含另一个。输出给定线段集的最大子集大小。

猜你喜欢

转载自blog.csdn.net/weixin_46434074/article/details/107834854