cf 653

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


//排序去重后判断是否有3个连续相差为1的数

#include <bits/stdc++.h>
using namespace std;

int a[1000];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",a+i);
    }
    sort(a,a+n);
    int i=0,j=1;
    while(j<n)
    {
        if(a[j]!=a[i])
        {
            swap(a[++i],a[j]);
        }
        j++;
    }
    int flag=0;
    for(int k=0;k<=i-2;k++)
    {
        if(a[k]+1==a[k+1]&&a[k+1]+1==a[k+2])
            flag=1;
    }
    if(flag)
        puts("YES");
    else
        puts("NO");

    return 0;
}


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


给你由a,b,c,d,e,f六个字符组成长度为n的字符串经过q中的若干个操作是否可以变成字母a

这题我们可以从后往前推,由a经过若干个操作是否可以变成长度为n的字符串  这里需要注意只能替换字符串的前两个字母



#include <bits/stdc++.h>
using namespace std;

vector<string>v[1000];
map<string,int>mm;
map<char,string>::iterator it;
int n,b;
void dfs(string s)
{
    if(s.size()>n)return;
    if(s.size()==n)
    {
        mm[s]++;
       // cout<<s<<endl;
    }
    else
    {
            char c=s[0];
            for(int k=0;k<v[c].size();k++)
            {
                s.replace(0,1,v[c][k]);
                dfs(s);
                s.replace(0,2,1,c);
            }
    }
}
int main()
{
    scanf("%d%d",&n,&b);
    string s;
    char c;
    mm.clear();
    while(b--)
    {

        cin>>s>>c;
        v[c].push_back(s);
    }
    for(int i=0;i<200;i++)
    {
        for(int k=0;k<v[i].size();k++)
        {
            s=v[i][k];
            c=char(i);
            if(c=='a')
            {
                dfs(s);
            }
        }
    }
    printf("%d\n",mm.size());
    return 0;
}

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


给你n个数问你有多少种方法可以交换一次序列中的a[i]  a[j] 使得序列变成nice序列 nice序列的定义为 奇数下标的a[i] <a[i+1]  偶数下标的数a[i]>a[i+1]


我们先可以遍历一遍序列找到有多少个不符合nice序列定义的数 如果a[i]不符合nice定义记录下不符合的数的下标i 和i +1  当个数大于8时 不可能经过一次交换得到nice序列 3 3 4 5 6 7  这个就刚好为吧 交换一次可以变成nice序列 如果小于8的话我们可以从记录下的下标每一个去寻找符合nice序列的数   

#include <bits/stdc++.h>
using namespace std;
const int maxn=150010;
const int inf=(1<<30);
int a[maxn];
int mark[maxn];
int cn;
//由于序列的其他位置都符合nice的定义只有记录下来的个数不符合 所以交换后只需判断是否全部都符合定义就可以了
int check()
{
    int flag=0;
    for(int i=0;i<cn;i++)
    {
        int t=mark[i];
        if(t%2==0&&a[t-1]<a[t]&&a[t]>a[t+1])
            flag++;
        else if(a[t-1]>a[t]&&a[t]<a[t+1])
            flag++;
    }
    return flag==cn?1:0;
}
int main()
{
    int n;
    scanf("%d",&n);
    a[0]=inf;
    memset(mark,-1,sizeof(mark));
    for(int i=1;i<=n;i++)
        scanf("%d",a+i);
    a[n+1]=n%2?inf:0;
    cn=0;
    for(int i=1;i<n;i++)
    {
        if(i%2==1)
        {
            if(a[i]>=a[i+1])
            {
                mark[cn++]=i;
                mark[cn++]=i+1;
            }
        }
        else
        {
            if(a[i]<=a[i+1])
            {
                mark[cn++]=i;
                mark[cn++]=i+1;
            }
        }
    }
    if(cn>8)
        puts("0");
    else
    {
        int res=0;
        int flag=0;
        map<pair<int,int>,int>m; //记录交换的数防止重复交换
        m.clear();
        for(int i=0;i<cn;i++)
        {
            for(int k=1;k<=n;k++)
            {
                flag=0;
                int t=mark[i];
                swap(a[t],a[k]);
                if(k%2==1&&a[k-1]>a[k]&&a[k]<a[k+1]&&check())
                {
                    if(m[make_pair(t,k)]==1||m[make_pair(k,t)]==1)
                        flag=0;
                    else
                        flag=1;
                    m[make_pair(t,k)]=1;
                    m[make_pair(k,t)]=1;
                }
                if(k%2==0&&a[k-1]<a[k]&&a[k]>a[k+1]&&check())
                {
                    if(m[make_pair(t,k)]==1||m[make_pair(k,t)]==1)
                        flag=0;
                    else
                        flag=1;
                    m[make_pair(t,k)]=1;
                    m[make_pair(k,t)]=1;
                }
                if(flag)
                    res++;
                swap(a[k],a[t]);
            }
        }
        printf("%d\n",res);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值