codeforces#323(div2) D. Once Again... 求周期数列的LIS
You are given an array of positive integers a1, a2, ..., an × T of length n × T. We know that for any i > n it is true that ai = ai - n. Find the length of the longest non-decreasing sequence of the given array.
The first line contains two space-separated integers: n, T (1 ≤ n ≤ 100, 1 ≤ T ≤ 107). The second line contains n space-separated integers a1, a2, ..., an (1 ≤ ai ≤ 300).
Print a single number — the length of a sought sequence.
4 3
3 1 4 2
5
The array given in the sample looks like that: 3, 1, 4, 2, 3, 1, 4, 2, 3, 1, 4, 2. The elements in bold form the largest non-decreasing subsequence.
这题有点乱搞的意味。。思考的过程应该是这样的:
首先,先考虑T很大时,我们限定每个数只能用一次,那么LIS最多不会超过n,LIS所在的子数列长度最多也就是n*n,即每个周期都只选一个的情况,因此我们可以先求出n个周期的LIS。还剩下T-n个周期,这些周期可以插在LIS用到的那n个周期中间,这T-n个周期每个周期也要选一些数,那么选那些数呢,当然是选出现次数最多的!这样答案就是LIS(1,n*n)+(T-n)*max_cnt。
上面是T>n的情况,对于T<=n的情况,直接求LIS即可,问题就此解决!
完全不难啊。。。
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=(1<<29); int n,T; int a[maxn]; int b[maxn],len; int cnt[maxn]; int lis(int *a,int n) { len=0;b[++len]=a[1]; REP(i,2,n){ if(a[i]>=b[len]) b[++len]=a[i]; else{ int p=upper_bound(b+1,b+len+1,a[i])-b; b[p]=a[i]; } } return len; } int main() { while(cin>>n>>T){ MS0(cnt); int max_cnt=0; REP(i,1,n) scanf("%I64d",&a[i]),cnt[a[i]]++,max_cnt=max(max_cnt,cnt[a[i]]); REP(i,1,n-1){ REP(j,1,n){ a[i*n+j]=a[j]; } } ll ans=0; if(T<=n) ans=lis(a,n*T); else{ ans=lis(a,n*n)+max_cnt*(T-n); } printf("%I64d ",ans); } return 0; }