CF Round #634

CF Round #634

A.数学

给定a个子,你现在要把它分成两堆AB,保证A的数量大于B,且B至少有一个

思路:奇偶分开即可

B.构造

给定n,a,b

你现在要构造一个长度为n的字符串使得它每相邻a个中出现b个字符

思路:构造长度为a的循环节,其中前0-b-1位是不同字符,后b-a-1位是相同字符

然后,i遍历n,输出a[i%a.len]即可

C.数学

给定一个序列

你要对他们分队

第一队全员不同,第二队全员相同,且两者数量相同

求这个数量的最大值

思路:暴力统计,要注意第二队的元素可能出现在第一队里,取最大值要注意

D.数独,构造

给定一个已成立数独

你至多改掉上面9个元素,使得它,满足:

输出你破坏的数独

思路:九行九列九大格,刚好每行每列每大格被破坏一个,例如:

a[1][1]++;
a[2][4]++;
a[3][7]++;
a[4][2]++;
a[5][5]++;
a[6][8]++;
a[7][3]++;
a[8][6]++;
a[9][9]++;

E.前缀和(E1&E2)

题意:

我们称满足条件的序列,它

1)回文

2)它至多有三块连续的相同字符串

给定你一个序列,从中求满足条件的最大的子序列

强调:序列中所有数取值从1->200(E1:1->26)

思路:

这题关键在于看到数据范围,它很小,200不到,这其实就是一个提醒

记录pre[元素种类][pos],何元素何位置的前缀和

并且为每个种类开一个vector记录它出现过的位置

然后进行枚举,第一层枚举前后串种类,第二层枚举数量,第三次枚举中间种类,这里就要用前缀和了

注意aaaaa这种,要特判

AC:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
#define INF 1e10+5
#define maxn 105
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define uint unsigned int
#define re register
inline int read()
{
	re int t=0;
	re char v=getchar();
	while(v<'0')v=getchar();
	while(v>='0')
	{
	    t=(t<<3)+(t<<1)+v-48;
	    v=getchar();
	}
    return t;
}
int pre[201][200000];
vector<int>num[201];
void solve()
{
    int n=read();
    int cur;
    for(int i=0;i<201;i++)num[i].clear();
    for(int i=0;i<n;i++)
    {
        cin>>cur;
        for(int j=1;j<=200;j++)pre[j][i]=(i?pre[j][i-1]:0);
        pre[cur][i]++;
        num[cur].push_back(i);
    }
    int ans=1;
    for(int i=1;i<=200;i++)
    {
        int siz=num[i].size();
        ans=max(ans,siz);
        for(int j=0;j<siz/2;j++)
        {
            for(int k=1;k<=200;k++)
            {
                if(k!=i)ans=max(ans,2*(j+1)-pre[k][num[i][j]]+pre[k][num[i][siz-j-1]]);
            }
        }
    }
    cout<<ans<<"
";
}
int main()
{
    int t;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/et3-tsy/p/12697911.html