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;
    }
  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/baihualiaoluan/p/12267106.html
Copyright © 2011-2022 走看看