zoukankan      html  css  js  c++  java
  • CF#612(Div.2)

    A. Angry Students

    题意:

    给你一个字符串(只包含’A’,’P’),每过1秒, 对于每一个A,假如它右边那个不是A,它会把他右面那个变成A。问最多过几秒,整个串中A的数目不会增加

    思路

    这题数据范围非常小,因此可以用bfs求解

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    int vis[150];
    int ans = 0;
    void solve(int n)
    {
        queue<int> q;
        for(int i = 1;i<=n;++i)
            if(vis[i]==0)
                q.push(i);
        while(!q.empty())
        {
            int x = q.front();
            q.pop();
            ans = max(ans,vis[x]);
            if(x+1<=n&&vis[x+1]==-1)
            {
                vis[x+1] = vis[x]+1;
                q.push(x+1);
            }
        }
        return ;
    }
    int main()
    {
      int t;
      cin >> t;
      while(t--)
      {
          int n;
          cin >> n;
          for(int i = 1;i<=n;i++)
            vis[i] = -1;
          string s;
          cin >> s;
          for(int i = 0;i<n;i++)
          {
              if(s[i]=='A')
                vis[i+1] = 0;
          }
          ans = 0;
          solve(n);
          ans = max(ans,0);
          cout << ans << endl;
      }
        return 0;
    }

    B. Hyperset

    题意:

    给你n个长度为k的字符串(只包括"S", "E", or "T".),对于每三个串,如果这三个串每一个元素完全相同或者完全不同,可以称为一个set,问总共有几对set

    思路:

    这里的数据范围是比较小的,我们可以通过枚举两个串然后根据上面的条件构造出第三个串来,检查一下这个串是否存在就行,要注意我们这样枚举的话每一组合是数了3次的,所以要除以3

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 1500+10;
    string str[maxn];
    set<string> s;
    int main()
    {
       int n,k;
       cin >> n >>k;
       for(int i = 0;i<n;++i)
       {
           cin >>str[i];
           s.insert(str[i]);
       }
       int all = 'S'+'T'+'E';
       string q ;
       q.resize(k);
       int res = 0;
       for(int i = 0;i<n;i++)
       {
           for(int j = i+1;j<n;++j)
           {
               for(int l = 0;l<k;++l)
               {
                   if(str[i][l]==str[j][l])
                   {
                       q[l] = str[i][l];
                   }
                   else
                   {
                       q[l] = all-str[i][l]-str[j][l];
                   }
               }
               if(s.find(q)!=s.end())
                ++res;
           }
       }
       cout << res/3 << endl;
        return 0;
    }

    C. Garland

    题意:

    给一个1-n的排列,但排列中的某些数被移去了,,定义一个概念complexity它的值为排列中奇偶性不同的相邻两数的对数。,要求输出complexity值最小的排列。

    思路:

    定义一个四维dp数组 dp[i][even][odd][2] ,代表到第i个位置时,已经填了even个偶数,odd个奇数,此时在第i个位置填入(奇数或偶数)的最小答案。

    在探讨转移方程之前,我们需要先计算总共空出多少个偶数和奇数,以及在第i个位置之前一共有多少个待填位置,定义为pre[i]

    我们首先要枚举前三维,假如现在枚举的偶数以及奇数数目符合要求,这时如果当前位置已经有数,

    如果是奇数,若上一位为偶数,则对答案贡献+1

    f[i][j][k][0] = min(f[i - 1][j][k][0], f[i - 1][j][k][1] + 1);

    若是偶数

    f[i][j][k][1] = min(f[i - 1][j][k][0] + 1, f[i - 1][j][k][1]);

    如果当前位置已经没有数,则需要两种情况都要考虑,同时要注意的时,我们现在是需要往里面填数的,所以转移方程略有不同。

    f[i][j][k][0] = min(f[i - 1][j - 1][k][0], f[i - 1][j - 1][k][1] + 1);

    f[i][j][k][1] = min(f[i - 1][j][k - 1][0] + 1, f[i - 1][j][k - 1][1]);

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
     
    using namespace std;
    const int N = 105;
    int f[N][N][N][2]={0};
    int a[N];
    int pre[N];
    int odd, even;
    int main()
    {
        int n;
        scanf("%d", &n);
     
        for (int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
            if (a[i] > 0)
            {
                if (a[i] % 2 == 0)
                    ++even;
                else
                    ++odd;
                pre[i] = pre[i - 1];
            }
            else
            {
                pre[i] = pre[i - 1] + 1;
            }
        }
     
        if (n % 2 == 0)
        {
            even = n / 2 - even;
            odd = n / 2 - odd;
        }
        else
        {
            even = n / 2 - even;
            odd = n / 2 + 1 - odd;
        }
            memset(f, 0x3f, sizeof f);
        //第二维和第三维为填充的偶数个数和奇数个数
       // cout << 0x3f<< endl;
        f[0][0][0][0] = 0;
        f[0][0][0][1] = 0;
     
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 0; j <= even; ++j)
            {
                for (int k = 0; k <= odd; ++k)
                {
                    if (a[i] > 0)
                    {
                        if (j + k <= pre[i])
                        {
                            if (a[i] % 2 == 0)
                            {
                                f[i][j][k][0] = min(f[i - 1][j][k][0], f[i - 1][j][k][1] + 1);
                            }
                            else
                            {
                                f[i][j][k][1] = min(f[i - 1][j][k][0] + 1, f[i - 1][j][k][1]);
                            }
                        }
                    }
                    else
                    {
                        if (j + k <= pre[i])
                        {
                            f[i][j][k][0] = min(f[i - 1][j - 1][k][0], f[i - 1][j - 1][k][1] + 1);
                            f[i][j][k][1] = min(f[i - 1][j][k - 1][0] + 1, f[i - 1][j][k - 1][1]);
                        }
                    }
                }
            }
        }
     
        int res = 0x3f3f3f3f;
        res = min(f[n][even][odd][0], f[n][even][odd][1]);
     
        printf("%d
    ", res);
     
     
        return 0;

    D. Numbers on Tree

    题意:

    给你一个有根树,对于这棵树,每一个结点上都有一个数字ai,同时定义一个值ci,代表第以第i个结点为根的子树中值比自己大的数的根数,现在给出每个节点的父节点以及ci,请输出YES和任何符合条件的a数组或NO

    思路:

    首先通过给出的信息,我们能够构造出这棵树,对于每个结点i,我们可以得到它的子树上有多少个结点,定义为sub[i]。假如子树上的结点数要比给出的c值要小,则一定输出NO,为了简便思考,我们可以假定a数组是1-n的一个排列,对于每一个结点,我们只要保证正好有c[i]个没有被选取的数即可,详细细节可以看代码。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e3+3;
    int n,c[N],ans[N],sub[N];
    bool vis[N],f;
    vector<int>pic[N];
    void dfs(int num)
    {
        if(!f)
            return ;
        int cnt = 0;
        for(int i = 1;i<=n;++i)
        {
            if(!vis[i])
                cnt++;
            if(cnt==c[num]+1)
            {
                ans[num] = i;
                vis[i] =1;
                break;
            }
        }
        for(int i = 0;i<pic[num].size();++i)
        {
            dfs(pic[num][i]);
            sub[num]+=sub[pic[num][i]];
        }
        if(sub[num]<c[num])
        {
            f = 0;
            return;
        }
    }
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            int root,p;
            for(int i = 0;i<=n;++i)
                pic[i].clear();
            memset(ans,0,sizeof(ans));
            memset(vis,0,sizeof(vis));
            for(int i =1;i<=n;++i)
            {
                scanf("%d %d",&p,&c[i]);
                if(p==0)
                    root= i;
                else
                    pic[p].push_back(i);
            }
            for(int i = 1;i<=n;++i)
            {
                sub[i] = pic[i].size();
            }
            f = 1;
            dfs(root);
            if(f)
            {
                printf("YES
    ");
                for(int i = 1;i<=n;++i)
                {
                    printf("%d%c",ans[i],i==n?'
    ':' ');
                }
            }
            else
                printf("NO
    ");
        }
        return 0;
    }

    E1. Madhouse (Easy version)

    题意:

    交互题,题目给出一个字符串的长度为n,你可对其进行不超过三次询问,格式为

    l  r 系统会返回s[l]-s[r]的所有子串(每个子串是乱序的),同时要求总返回的子串数不能超过(n+1^2

    然后要求输出该字符串是什么,格式为

    s

    思路:

    这个题事实上只需要询问两次就够了,一个是1-n,另一个是2-n。下面简述下做法

    abcd为例吧

    第一次询问

    长度为1a , b , c ,d

    长度为2ab, bc, cd

    长度为3abcbcd

    长度为4abcd

    第二次询问

    长度为1b , c ,d

    长度为2bc, cd

    长度为3bcd

    通过观察我们可以发现,

    长度为1时,第一次比第二次多一个字符串a,我们这样就得到字符串的第1个元素。

    长度为2时,第一次比第二次多出ab,此时a是我们已知的元素,而b正好是第二个元素。

    以此类推,就可以得到最终结果。

    最后要特判n=1时的情况。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    vector<string>vec[105];
    map<string,int>mp,mp1;
    string ans;
    int n;
    void solve()
    {
        ans.resize(n);
        int res = 0;
        for(int i = 1;i<=n;++i)
        {
            mp1.clear();
            string tmp;
            for(int j = 0;j<vec[i].size();++j)
            {
                mp1[vec[i][j]]++;
            }
            for(int j = 0;j<vec[i].size();++j)
            {
                if(mp.find(vec[i][j])==mp.end()||mp[vec[i][j]]!=mp1[vec[i][j]])
                {
                    tmp = vec[i][j];
                }
            }
            int sum = 0;
            for(int i = 0;i<tmp.size();++i)
            {
                sum+=(tmp[i]-'a');
            }
            ans[i-1] = sum-res+'a';
            res = sum;
        }
        cout << "! " << ans << endl;
    }
    int main()
    {
       // int n;
        cin >> n;string s;
        if(n==1)
        {
            cout << "? 1 1" << endl;
     
            cin >> s;
            cout << "! " << s << endl;
        }
        else
        {
            cout << "? 1 " << n << endl;
            for(int i = 0;i<n*(n+1)/2;++i)
            {
                cin >> s;
                sort(s.begin(),s.end());
                vec[s.size()].push_back(s);
            }
            cout << "? 2 " << n << endl;
            for(int i = 0;i<n*(n-1)/2;++i)
            {
                cin >> s;
                sort(s.begin(),s.end());
                mp[s]++;
            }
            solve();
        }
        return 0;
    }
  • 相关阅读:
    angualr清除定时器
    flex布局常用属性
    将数组分割为几个等长度的子数组(使用slice)
    vue+element搭建的后台管理系统
    世界这么大,我想去看看!!!
    angularJs自定义指令(directive)实现滑块滑动
    适用初学者:vue2.0构建单页应用最佳实战
    笔记本win10安装node的尖酸历程。。。。。。
    js对数组处理(数组里边相同元素提取成map)
    快速搞定用Vue+Webpack搭建前端项目(学习好久了,该写点东西了......)
  • 原文地址:https://www.cnblogs.com/baihualiaoluan/p/12267106.html
Copyright © 2011-2022 走看看