码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces-1335-E Three Blocks Palindrome

时间:2020-04-14 22:44:12      阅读:74      评论:0      收藏:0      [点我收藏+]

标签:name   main   两种   ++   lse   using   test   memset   i++   

codeforces-1335-E Three Blocks Palindrome

传送门:

easy:https://codeforces.com/contest/1335/problem/E1

hard:https://codeforces.com/contest/1335/problem/E2

题意:

定义 three blocks palindrome 为 aaaaabbbaaaaa,其中两边的a必须个数相等 而且序列中只存在两种元素

1 1 1 2 3 2 1 1 1 是不可以的 1 1 1 2 1 2 1 1 1 也是不可以的

给你一段序列 找到最长的 three blocks palindrome 子序列(可以不连续)

这个题 是个纯暴力

说一下思路

 

 用一个前缀和 sum[i][j] 记下来在 i 这个位置有多少 j    1<=i<=n<=2e5      1<= j = a[i]<=200

把a[i]出现过的位置记下来,后面有用,我是用的vector

然后遍历1-200 内的每一个数作为上面的a,也就是在两边的部分 更新最大值

找到了 a ,在每两个 a 之间找到(这两个a中间夹着的重复的数的最大值+min(1到左面的a的位置有多少a,右面的a的位置到结尾有多少a )*2 )的最大值

不理解??

5 5 5 5 5 5 5 1 1 2 3 2 1 1 1  a=1时最优的选择是什么呢 1 1 2 2 1 1 因为要保证两边a的距离相等所以取小 因为a=1指定没有a=5长,所以每次取最大

这个在每两个a之间找,暴力的话可以套俩循环,easy是指定能过的,hard没有试,要做一下优化

想一下 1 2 3 4 5 6 7 8 这些个位置,如果是找1 8 max(之间中间夹着的重复的数)一定比1 5之间的 max(之间中间夹着的重复的数) 要多,如果右面是位置5的情况比较大,那一定是1往右移了

所以我们duck不必套俩循环,一左一右往中间缩就好了

 

 行了,去模拟吧

 

还有 sum 不用memset 初始化会tle 他是每次覆盖上去的

j<ve[i].size()/2 不能写成j*2<ve[i].size()        j=1,ve[i].size()=3会错

maxx初值赋成1 因为最小的长度就是它本身也是1,而且这种情况根本无法更新最大值,赋成-1或者0你就凉了

easy版代码就不粘了,比这个还要暴力呢

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
int a[200009];
int sum[200009][209];//i j 在i处有多少j
vector<int>ve[300];
int main()
{
    int _;
    for(scanf("%d",&_); _; _--)
    {
        for(int i=0; i<202; i++) ve[i].clear();
        int n;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            ve[a[i]].push_back(i);
            for(int j=1; j<=200; j++)
            {
                if(j==a[i]) sum[i][j]=sum[i-1][j]+1;
                else sum[i][j]=sum[i-1][j];
            }
        }
        int maxx=1;
        for(int i=1; i<=200; i++)
        {
            for(int j=0; j<ve[i].size()/2; j++)
            {
                int mx=0;
                int k=ve[i].size()-j-1;
                for(int k_=1; k_<=200; k_++)
                {
                    int sm=sum[ve[i][k]-1][k_]-sum[ve[i][j]][k_];
                    mx=max(mx,sm);
                }
                maxx=max(mx+2*(j+1),maxx);
            }
        }
        printf("%d\n",maxx);
    }
    return 0;
}

 

codeforces-1335-E Three Blocks Palindrome

标签:name   main   两种   ++   lse   using   test   memset   i++   

原文地址:https://www.cnblogs.com/YangKun-/p/12701389.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!