2016多校联合第三场 HDU5760

来源:互联网 发布:网络借贷安全班会 编辑:程序博客网 时间:2024/06/06 04:10

给你个n,然后n个数,你要找到一个最长的序列s,输出其长度,并且输出不同的s的个数。s序列必须是回文的,并且中间最小,往两边依次增大,可以相等。s1s2不同当且仅当长度不同或者存在某位s1[i]!=s2[i]

这个dp比较难。

n范围比较小,先把a数组离散化。方便之后处理。再预处理两个数组pre[i][j] nxt[i][j]分别表示以i起左边第一个等于j的数的位置和以i起右边第一个等于j的数的位置。

dp[l][r]元组表示a[l]==a[r]的时候的最长s串和最长串个数。那么有dp[l][r]=max{dp[nxt[l][c]][pre[r][c]]+2}枚举c再枚举区间的复杂度是n3显然超时。

如果固定l,逐渐向右扫的时候,dp值肯定是越来越优的。我们设一个临时变量ans来表示l右边开始某位置的最优值,然后往右扫的同时就可以直接用此临时变量更新我们的dp[l][r],当然,也需要把ans的值也更新。当遇到相同值的时候,要加上数量,然后就是去重

每次更新ans的时候,如果发现当前串的长度等于ans那么需要把个数加进ans但是如果之前加过一样的长度,并且二者首尾一样,那么说明后者包含了更多的res(因为范围更大)那么减去原来的,加上后来的,刚好不重不漏。

////  Created by Running Photon//  Copyright (c) 2015 Running Photon. All rights reserved.//#include <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <sstream>#include <set>#include <vector>#include <stack>#define ALL(x) x.begin(), x.end()#define INS(x) inserter(x, x,begin())#define ll long long#define CLR(x) memset(x, 0, sizeof x)using namespace std;const int inf = 0x3f3f3f3f;const int MOD = 1e9 + 7;const int maxn = 1e6 + 10;const int maxv = 5e3 + 10;const double eps = 1e-9;int a[maxv];int pre[maxv][maxv], nxt[maxv][maxv];typedef pair <int, int> sta;sta dp[maxv][maxv];int main() {#ifdef LOCAL    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);#endif//  ios_base::sync_with_stdio(0);    int n;    while(scanf("%d", &n) != EOF) {        std::vector<int> xs;        for(int i = 1; i <= n; i++) {            int x;            scanf("%d", &x);            xs.push_back(x);            a[i] = x;        }        sort(ALL(xs));        xs.resize(unique(ALL(xs)) - xs.begin());        for(int i = 1; i <= n; i++) {            a[i] = lower_bound(ALL(xs), a[i]) - xs.begin() + 1;        }        // for(int i = 1; i <= n; i++) {        //  printf("%d ", a[i]);        // }        // puts("");        memset(pre, -1, sizeof pre);        memset(nxt, -1, sizeof nxt);        int big = xs.size();        for(int i = 0; i <= n + 1; i++) {            for(int j = i + 1; j <= n; j++) {                if(nxt[i][a[j]] == -1) {                    nxt[i][a[j]] = j;                }            }            for(int j = i - 1; j > 0; j--) {                if(pre[i][a[j]] == -1) {                    pre[i][a[j]] = j;                }            }        }        for(int i = n; i > 0; i--) {            dp[i][i] = sta(1, 1);            sta ans = sta(0, 1);            for(int j = i + 1; j <= n; j++) {                dp[i][j] = sta(0, 0);                if(a[i] == a[j]) {                    // printf("dp[%d][%d] = %d %d\n", i, j, dp[i][j].first, dp[i][j].second);                    dp[i][j] = sta(ans.first + 2, ans.second);                }                if(a[i] >= a[j]) {                    int head = nxt[i][a[j]];                    if(head == -1) continue;                    if(dp[head][j].first > ans.first) {                        ans = dp[head][j];                    }                    else if(dp[head][j].first == ans.first) {                        int p = pre[j][a[j]];                        if(p != -1 && dp[head][p].first == dp[head][j].first) ans.second -= dp[head][p].second;                        if(ans.second < 0) ans.second += MOD;                        ans.second = (ans.second + dp[head][j].second) % MOD;                    }                }            }        }        sta ans(0, 0);        for(int c = 1; c <= big; c++) {            int head = nxt[0][c];            int tail = pre[n+1][c];            if(head == -1 || tail == -1) continue;            // printf("dp[%d][%d] = %d\n", head, tail, dp[head][tail]);            if(ans.first < dp[head][tail].first) {                ans = dp[head][tail];            }            else if(ans.first == dp[head][tail].first) {                ans.second = (ans.second + dp[head][tail].second) % MOD;            }        }        printf("%d %d\n", ans.first, ans.second);    }       return 0;}
0 0
原创粉丝点击