您的位置:首页 > 大数据 > 人工智能

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

2015-10-04 13:46 447 查看
给出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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: