• 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;
    }
    
  • 相关阅读:
    php 文件下载 重命名
    [转载]北漂一族年终总结:在北京混必备的六大能力
    出去转了一转,便利店......
    来京第一天
    生活脚步,不停地走......
    键盘控制层的移动javascript
    离开告别...重新开始...
    夜未眠,三字诗......
    我喜欢这首歌......
    Foxmail邮件发不出去,都是Mcafee惹得祸
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12748438.html
Copyright © 2020-2023  润新知