首页 > 其他 > 详细

Codeforces Round #661 (Div. 3)(A->D)

时间:2020-08-06 23:23:13      阅读:81      评论:0      收藏:0      [点我收藏+]

A:http://codeforces.com/contest/1399/problem/A

解析:

不多说了,直接sort,判是否存在相邻差>1

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn=60;
int l[maxn],r[maxn];
char ch[3*maxn];
int a[maxn];
int pos[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        if(n==1)
        {
            cout<<"YES"<<endl;continue;
        }
        sort(a+1,a+1+n);
        int ok=0;
        for(int i=2;i<=n;i++)
            if(abs(a[i]-a[i-1])>1)
            {
                ok=1;break;
            }
        if(ok)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
}

B:http://codeforces.com/contest/1399/problem/B

题意:

长度为n的a[]和b[]

三种操作:

1. ai--

2. bi--

3. ai和bi同时减1

分别把a[]和b[]变成全相等数组,问最少需要的操作数。a[]不一定要和b[]相等。

解析:

因为只存在自减操作,所以元素并不会增大。所以最少需要的操作,一定是a[]和b[]变成对应的最小值。

所以先找到各自的最小值。

遍历a[]和b[],对于每一个ai,bi,算出俩差值,先同时减,然后较大的再自减就可以了。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=60;
const int mod=1e9+7;
int l[maxn],r[maxn];
char ch[3*maxn];
ll a[maxn];
ll b[maxn];
ll c[maxn],d[maxn];
int pos[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        map<ll,ll>m1;
        map<ll,ll>m2;
        int tot1=0,tot2=0;
        ll mina=mod,minb=mod;
        for(int i=1;i<=n;i++)
            {
                cin>>a[i];
                mina=min(a[i],mina);
            }
        for(int i=1;i<=n;i++)
            {
                cin>>b[i];
                minb=min(b[i],minb);
            }
        ll cnt=0;
        for(int i=1;i<=n;i++)
        {
            int m1=a[i]-mina;
            int m2=b[i]-minb;
            if(m1>m2)
            {
                cnt+=m2;
                cnt+=m1-m2;
            }
            if(m1==m2)
                cnt+=m1;
            if(m1<m2)
            {
                cnt+=m1;
                cnt+=m2-m1;
            }
        }
        cout<<cnt<<endl;
    }
}

C:http://codeforces.com/contest/1399/problem/C

题意:

有n个人想参加划船比赛。第i个参与者的权重是wi。

只有两人组成的团队可以参加比赛。

如果有k个团队(a1,b1),(a2,b2),…,(ak,bk),其中ai是第i个团队的第一个参与者的权重,bi是第二个团队的权重第i个团队的参与者,则必须满足条件a1 + b1 = a2 + b2 =?= ak + bk = s,其中s是每个团队的总权重。问有多少个团队可以参赛。

解析:

n==50,直接三重for暴力遍历每一个和值即可。

先统计不同的两两和,然后对它们进行暴力枚举,看每一个值能组成多少团队,取最大即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=60;
const int mod=1e9+7;
int l[maxn],r[maxn];
char ch[3*maxn];
int a[maxn];
int b[8*maxn];
int vis[maxn];
ll c[maxn],d[maxn];
int pos[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            {
                cin>>a[i];
            }
        int tot=0;
        map<int,int>m1;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int md=a[i]+a[j];
                if(!m1[md])
                    b[tot++]=md;
                m1[md]=1;
            }
        }
        int maxx=0;
        for(int i=0;i<tot;i++)
        {
            memset(vis,0,sizeof(vis));
            int cnt=0;
            int md=b[i];
            for(int j=1;j<=n;j++)
            {
                for(int c=j+1;c<=n;c++)
                {
                    int md2=a[j]+a[c];
                    if(!vis[j]&&!vis[c]&&md2==md)
                    {
                        cnt++;
                        vis[j]=1;
                        vis[c]=1;
                    }
                }
            }
            maxx=max(maxx,cnt);
        }
        cout<<maxx<<endl;
    }
}

D:http://codeforces.com/contest/1399/problem/D

题意:

给定一个字符串由0/1组成,问最少有几个字符串是01间隔的(010101……或者101010……)。输出最少的个数和每个字符在第几个子字符串。

解析:

是存在贪心思想的。

因为要想个数更少,肯定对于遍历到的每个0,要接到它之前已经存在的0101...上,而不是另开一个新子串,只有之前没得接的时候,才需要另开新子串。

用到两个队列,一个是stack st[2],用来存以0/1结尾的符合条件的子序列编号。

vector用来存每个字符属于第几个子串。

接下来看注释吧:

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        string s;
        cin>>s;
        stack<int>st[2];
        vector<int>vv;
        int len=s.length();
        int all=1;
        for(int i=0;i<len;i++)
        {
            int now=s[i]-0;
            if(st[now^1].empty())    //now对应的字符,如果没得接,就新开一个子串 
            {
                st[now^1].push(all++);
            }
            int top=st[now^1].top();    //找到s[i]可以接的子串编号 
            vv.push_back(top);        //存入s[i]所属子串编号 
            st[now^1].pop();    // 现在的第top子串,已经接上了s[i],那么它的末尾就变了, 0->1/1->0,所以要把top传过去 
            st[now].push(top);     
        }
        all--;
        cout<<all<<endl;
        for(int i=0;i<vv.size();i++)
            cout<<vv[i]<<" ";
            cout<<endl;
    }
}

 

Codeforces Round #661 (Div. 3)(A->D)

原文:https://www.cnblogs.com/liyexin/p/13449355.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!