CF#323-DIV2-D. Once Again-暴力贪心LIS

来源:互联网 发布:wps表格怎么刷新数据 编辑:程序博客网 时间:2024/04/30 12:12

给出n长度的字符串

重复t个周期

求LIS(最长非递减子序列)

由于n最大才100。。考虑最极端情况n=100,t=1e7

显然,我们只需要把前100段拼接起来,求一遍LIS

此后的t-100周期, 我们只需要 取 重复个数最多的那个元素。 一直重复t-100次得到的答案必然是最优的 (不可能有其他情况了)

例如 n=4;  

  6 2 2 3

前100次 我们取得的lis是100对 (2 2) 以及一个3

那么显然 重复最多次的元素是2,次数为2

剩下t-100次,我们只需要先把最后一个3 去掉,然后在t-100个周期 都取 重复次数最多的2,,最后补上一个3

也就是最后取得  100对(2 2) +  t-100对(2 2) + 3;


也就是 t<=100直接暴力,t>100,按上面的方法贪心就好

复杂度 n*n*logn


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <queue>#include <algorithm>#include <iostream>using namespace std;struct node{__int64 len;__int64 st,ed;};node dp[100000+5];//nlgn??????LIS ????__int64 tm[100000+5]; __int64 cmp(node a,node b){return tm[a.ed]<tm[b.ed];    //???????????????????LIS??????}__int64 min(__int64 a,__int64 b){return a<b?a:b;}__int64 max(__int64 a,__int64 b){return a>b?a:b;}int vis[305];int main(){__int64 n;__int64 t;scanf("%I64d%I64d",&n,&t);__int64 maxx=0;__int64 i,len; for (i=1;i<=n;i++){scanf("%I64d",&tm[i]);if (tm[i]>maxx)maxx=tm[i];vis[tm[i]]++;}int num_maxx=0;int maxx_i=0;for(i=1;i<=300;i++){if (vis[i]>num_maxx){num_maxx=vis[i];maxx_i=i;}  }__int64 cun_max=0;for (i=1;i<=n;i++){if (tm[i]==maxx)cun_max++;}for (i=n+1;i<=min(t,100)*n;i++){tm[i]=tm[i-n];}len=1;dp[1].len=len; dp[1].ed=1;  for (i=2;i<=min(t,100)*n;i++){if (tm[i]>=tm[dp[len].ed])      //???????????????????+1{len++;dp[len].len=len; dp[len].ed=i;}else{node tmp;tmp.ed=i;__int64 it= upper_bound(dp+1, dp+len+1,tmp,cmp)-&dp[1]+1; //????  ???????LIS?????е?????????????????滻dp[it].ed=i;}}if (t>100) {for (i=len;i>=1;i--){if (tm[dp[i].ed]==maxx_i)break;}__int64 now_len=len-i+1; __int64 t2=len-now_len+(t-100)*vis[maxx_i]+now_len;//其实就是 t2=len+(t-100)*vis[maxx_i]len=t2;}printf("%I64d\n",len); return 0;}


0 0
原创粉丝点击