• Codeforces 1335E2 Three Blocks Palindrome (hard version)(暴力)


    题目链接
    题目大意: 从一个序列里删除若干个序列,使其成为回文序列。求其中最长的回文序列。
      如果想最大限度的利用每一个数,那么左边区间的最后一个数字和右边区间的第一个数字肯定是相同的,同时,两边区间同一个数字出现的次数也是相同的。所以做法就是记录下每个数字出现的位置,然后分别从两头开始枚举,再从中间的区间找一个出现最多的数就行了。至于怎么快速的找出区间某个数字出现的次数,可以用前缀和来预处理然后遍历每个数字。因为每次枚举某个区间都要对所有数字进行遍历,显然(n)个数有(n)个位置,所以时间复杂度为(O(200n))

    const int maxn = 2e5+10;
    vector<int> pos[205];
    int arr[maxn], pre[maxn][205];
    int main(void) {
        int t;
        scanf("%d", &t);
        while(t--) {
            int n; 
            scanf("%d", &n);
            for (int i = 1; i<=n; ++i) {
                scanf("%d", &arr[i]); 
                ++pre[i][arr[i]];
                for (int j = 1; j<=205; ++j) pre[i][j]+=pre[i-1][j];
                pos[arr[i]].push_back(i);
            }
            int ans = 1;
            for (int i = 1; i<=200; ++i) {
                if (pos[i].empty()) continue;
                int sz = pos[i].size(), l = 0, r = sz-1, cnt = 1;
                //这里有一个pos[i][l]==pos[i][r]的情况(也就是序列中只有这一个数,不过ans初值为1可以忽略这种情况
                while(pos[i][l]<pos[i][r]) {
                    for (int j = 1; j<=200; ++j) ans = max(ans, cnt*2+pre[pos[i][r]-1][j]-pre[pos[i][l]][j]);
                    ++l, --r;
                    ++cnt;
                }
            }
            for (int i = 1; i<=200; ++i) {
                pos[i].clear();
                for (int j = 1; j<=200; ++j) pre[i][j] = 0;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    done apple两轮白人教你ci/cd
    done 没看完但是别处不考 沃尔玛sv大数据组的友好小哥
    done hitachi network四轮但是中规中矩
    23. Merge k Sorted Lists 合并k个排序链表
    SpringBoot+Spring常用注解总结
    MyBatisPlus 之 入门HelloWorld
    MyBatisPlus 之 集成MP
    MyBatisPlus 之 MyBatis 简介
    09月24日总结
    09月22日总结
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12748438.html
Copyright © 2020-2023  润新知