Codeforces #323 div2. D Once Again... dp LIS

来源:互联网 发布:淘宝卖家发布宝贝教程 编辑:程序博客网 时间:2024/04/25 17:14

题目

题目链接:http://codeforces.com/problemset/problem/582/B

题目来源:CF #323 div2D/ div1 B

简要题意:求序列a重复T次后的最长不下降子序列(LNDS)

数据范围:1n100;1T107;

题解

T比较小直接Θ(nTlognT)求出答案就行了。

T很大的时候,一个很直观的想法其中肯定有一段是平的,且这个ai应该是出现次数最大的。

设出现最多的为amax,出现camax次,LNDS中每段a对应的数字中除了全amax的以外应该每段都有至少两种数字,不然可以删掉这段换成一段amax,长度不会减小。

每增加一段LNDS的结尾至少增加1,所以最多只需要na就可以构造出成段amax外的序列

于是知道naamax为结尾的LNDS lislamax为开头的LNDS lisr就能知道答案。

结果为lisl+(T2n)camax+lisr

实现

使用类似LIS方法去做LNDS,lower_bound改成upper_bound即可

对于amax为结尾的LNDS,顺序求出再做个upper_bound就行了。

对于amax为开头的LNDS,无法用之前的结果直接做出来,需要转化。

amax为开头的LNDS就是反转序列中amax为结尾的最长不上升子序列。

继续统一,amax为开头的LNDS就是将序列反转,所有元素取相反数后amax为结尾的LNDS。

于是现在只要会求结尾LNDS就能搞了。

代码

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <stack>#include <queue>#include <string>#include <vector>#include <set>#include <map>#define pb push_back#define mp make_pair#define all(x) (x).begin(),(x).end()#define sz(x) ((int)(x).size())#define fi first#define se secondusing namespace std;typedef long long LL;typedef vector<int> VI;typedef pair<int,int> PII;LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}// headconst int INF = 0x3f3f3f3f;int LIS[100000];int RLIS[100000];int a[305];int cnt[305];int rev[305];int getLIS(int *LIS, int *a, int n, int t) {    int len = 0;    LIS[0] = INF;    for (int i = 0; i < t; i++) {        for (int j = 0; j < n; j++) {            *upper_bound(LIS, LIS+len, a[j]) = a[j];            if (LIS[len] != INF) LIS[++len] = INF;        }    }    return len;}int main(){    int n, t;    scanf("%d%d", &n, &t);    for (int i = 0; i < n; i++) {        scanf("%d", a+i);        cnt[a[i]]++;        rev[n-1-i] = -a[i];    }    if (t < 300) {        printf("%d\n", getLIS(LIS, a, n, t));        return 0;    }    int len = getLIS(LIS, a, n, n);    int lenr = getLIS(RLIS, rev, n, n);    int ans = 0;    for (int i = 0; i <= 300; i++) {        if (!cnt[i]) continue;        int temp = (t-2*n)*cnt[i];        temp += upper_bound(LIS, LIS+len, i)-LIS;        temp += upper_bound(RLIS, RLIS+lenr, -i)-RLIS;        ans = max(temp, ans);    }    printf("%d\n", ans);    return 0;}
0 0