比赛链接:https://vjudge.net/contest/341241
E:https://vjudge.net/contest/374548#problem/E
题意:给你一个长度为n的字符串s,问你里面有多少个不重复元素的xtCpc子串(不重复指的是在字符串同一位置上的字母只能使用一次)。
思路:第一步先暴力,那就是遍历一遍字符串每次遇到x就开始向后找t,若匹配成功则把相应字母变成其他非子串字母就好,以此类推。复杂度是O(n^2)。数据范围2e5,不想T了。
我们仔细观察一下子串,xtCpc,五个字母各自不同,那么对于原来的字符串其实也就只有这五个字母及其位置有用,这么一来,长度为n的字符串s就得到了优化。再暴力的想一想,对于s,在第一个x前面的tCpc都没有意义(匹配不到),在第二个x前面的tCpc对第二个x没有用(但对第一个有用),以此类推,得到对于第i个C前面的x,t都没用之类的结论。于是答案就出来,再想想用什么东西来维护呢?很容易想到先进先出的队列,用队列来存子串元素的位置,如果子串中后面元素的位置在前面元素的前方,那么这个元素必定没有意义,就弹出队列,如果在后方,就匹配成功以匹配下一个字母(由于题目说只能用一次,所以匹配成功后也要弹出这个元素)。每次c匹配成功ans就+1。至此代码也就写出来了。

//author CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=2e5+7;
const double pi=acos(-1);
using namespace std;
queue<int > p[128];
char a[maxn];
int main()
{

    ios::sync_with_stdio(false);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(a,0,sizeof(a));
        for(int i=0;i<128;i++)
        {
            while(!p[i].empty())
            {
                p[i].pop();
            }
        }
        scanf("%s",a);
        for(int i=0;i<n;i++)
        {
            p[int(a[i])].push(i);
        }
        char last_char;
        ll ans=0;
        ll place;
        if(!p[int('x')].empty())
        {
            place=p[int('x')].front();
            p[int('x')].pop();
            last_char='x';
        }
        else
        {
            cout<<0<<endl;
            return 0;
        }
        int f=1;
        //xtCpc
        while(f)
        {
            if(last_char=='x')
            {
                if(p[int('t')].empty())
                {
                    f=0;
                    break;
                }
                while(!p[int('t')].empty())
                {
                    if(p[int('t')].front()>place)
                    {
                        last_char='t';
                        place=p[int('t')].front();
                        p[int('t')].pop();
                        break;
                    }
                    else
                    {
                        p[int('t')].pop();
                    }
                }
            }

            else if(last_char=='t')
            {
                if(p[int('C')].empty())
                {
                    f=0;
                    break;
                }
                while(!p[int('C')].empty())
                {
                    if(p[int('C')].front()>place)
                    {
                        last_char='C';
                        place=p[int('C')].front();
                        p[int('C')].pop();
                        break;
                    }
                    else
                    {
                        p[int('C')].pop();
                    }
                }
            }

            else if(last_char=='C')
            {
                if(p[int('p')].empty())
                {
                    f=0;
                    break;
                }
                while(!p[int('p')].empty())
                {
                    if(p[int('p')].front()>place)
                    {
                        last_char='p';
                        place=p[int('p')].front();
                        p[int('p')].pop();
                        break;
                    }
                    else
                    {
                        p[int('p')].pop();
                    }
                }
            }

            else if(last_char=='p')
            {
                if(p[int('c')].empty())
                {
                    f=0;
                    break;
                }
                while(!p[int('c')].empty())
                {
                    if(p[int('c')].front()>place)
                    {
                        last_char='c';
                        place=p[int('c')].front();
                        p[int('c')].pop();
                        break;
                    }
                    else
                    {
                        p[int('c')].pop();
                    }
                }
            }

            else if(last_char=='c')//其实是说明已经找到一组了
            {
                ans++;
                if(p[int('x')].empty())
                {
                    f=0;
                    break;
                }
                else
                {
                    place=p[int('x')].front();
                    p[int('x')].pop();
                    last_char='x';
                }

            }

        }
        printf("%lld\n",ans);
    }
    //printf("%lld",ans);
     return 0;
}

K:https://vjudge.net/contest/374548#problem/K
参考博客:https://blog.csdn.net/qq_37748451/article/details/90368388
题意:给你十四张牌打麻将,有两种获胜方式,一种是shisanyao,另一种是jiulianbaodeng。我们来具体看下这两种方式背后的条件。
shisanyao:同时拥有东,南,西,北,红中,白板,发财,一条,九条,一万,九万,一筒,九筒这十三张牌,另外一张随意。
jiulianbaodeng:在万、筒、条中的某一种以1112345678999的形式加上1到9其中任意一张成立,注意必须是同一种牌,都是万,都是筒或都是条!
思路:
对于jiulianbaodeng,可以用三个数组来存对应数字,判断的时候看是否满足对应的形式就好。
对于shisanyao,结合jiulianbaodeng的三个数组,再来一个map<string,int>记录东,南,西,北,红中,白板,发财的出现次数。最后看一下是否满足这个条件就好。至此代码也就写出来了。

//author CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+7;
const double pi=acos(-1);
using namespace std;
//十三幺是东,南,西,北,红中,白板,发财和一条,九条,一万,九万,一筒,九筒 
//万、筒、条中的某一种以1112345678999的形式加上1到9其中任意一张成立 
string ss;
map <string,int> pai;
int p[10],w[10],s[10];
int p0,s0,w0;
int shuzi=0;
int jiu=1,shi=0;
int main()
{
    ios::sync_with_stdio(false);
    for (int i=0;i<14;i++)
    {
        cin>>ss;
        if(ss[1]=='p')
        {
            p[ss[0]-'0']++;
            shuzi++;
            p0++;
        }
        else if (ss[1]=='w')
        {
            w[ss[0]-'0']++;
            shuzi++;
            w0++;
        }
        else if (ss[1]=='s')
        {
            s[ss[0]-'0']++;
            shuzi++;
            s0++;
        }
        else
        {
            pai[string(ss)]++;    
        }
    } 
    if(s0==14)
    {
        if(s[1]<3||s[9]<3)
        {
            jiu=0;
        }
        for(int i=2;i<=8;i++)
        {
            if(s[i]<1)
            {
                jiu=0;
            }
        }
    }
    else if(p0==14)
    {
        if(p[1]<3||p[9]<3)
        {
            jiu=0;
        }
        for(int i=2;i<=8;i++)
        {
            if(p[i]<1)
            {
                jiu=0;
            }
        }
    }
    else if(w0==14)
    {
        if(w[1]<3||w[9]<3)
        {
            jiu=0;
        }
        for(int i=2;i<=8;i++)
        {
            if(w[i]<1)
            {
                jiu=0;
            }
        }
    }
    //以上是判断九莲宝灯 
    else if(s[1]>=1&&s[9]>=1&&p[1]>=1&&p[9]>=1&&w[1]>=1&&w[9]>=1&&pai["dong"]>=1&&pai["nan"]>=1&&pai["xi"]>=1&&pai["bei"]>=1&&pai["zhong"]>=1&&pai["fa"]>=1&&pai["bai"]>=1)
    {
        shi=1;
    } 
    if(shi)
    {
        cout<<"shisanyao!"<<endl;
    }
    else if(jiu)
    {
        cout<<"jiulianbaodeng"<<endl;
    }
    else
    {
        cout<<"I dont know!"<<endl;
    }
     return 0;
}

L:https://vjudge.net/contest/374548#problem/L
题意:就是对于单词,改变一下它非头尾的字母,你能不能说明这是一样的单词(具体看样例)
如果单词没变化,就输出Equal,如果是一样的单词,输出Yes,如果不一样,输出No。
思路:很容易想到桶排序,毕竟单词里面就是字母,除开头尾,中间部分每个字母次数一样,必然是Yes,再在这种情况下判断一下是不是Equal就好。至此代码也就出来了。

//author CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+7;
const double pi=acos(-1);
using namespace std;
int tong[26]={0};
int tong2[26]={0};
int main()
{
    ios::sync_with_stdio(false);
    string a,b;
    while(cin>>a>>b)
    {
        memset(tong,0,sizeof(tong));
        memset(tong2,0,sizeof(tong2));
        int n,m;
        n=a.length();
        m=b.length();
        if(n!=m)
        {
            cout<<"No"<<endl;
            continue;
        }
        //判断相等
        int f=1;
        for(int i=0;i<n;i++)
        {
            if(a[i]!=b[i])
            {
                f=0;
                break;
            }
        } 
        if(f)
        {
            cout<<"Equal"<<endl;
            continue;
        }
        int f2=1;
        if(a[0]==b[0]&&a[n-1]==b[n-1])
        {

            for(int i=1;i<n-1;i++)
            {
                tong[int(a[i]-'a')]++;
                tong2[int(b[i]-'a')]++;
            }
            for(int i=0;i<26;i++)
            {
                if(tong[i]!=tong2[i])
                {
                    f2=0;
                    cout<<"No"<<endl;
                    break;
                }
            }        
        }
        else
        {
            cout<<"No"<<endl;
            continue;
        }
        if(f2)
        {
            cout<<"Yes"<<endl;
        }
    }
     return 0;
}

写在最后:
打麻将杀我,考场上看了不知道多久就是没看懂!麻将真难。
这套就补三个,另外的题,根本就没人做出来。
以后可能想起来会补吧。