博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj4486: [Jsoi2015]串分割
阅读量:4983 次
发布时间:2019-06-12

本文共 2212 字,大约阅读时间需要 7 分钟。

肉丝哥哥钦定好题 话说我的blog现在为什么到处都是肉丝哥哥

先来想一个弱化版,假如能够n整除K怎么做?

把每个数字看成一个字符串,按字典序排名,这个可以后缀数组解决,然后暴力枚举每种情况,O(1)判两个长度为n/K的数字大小即可

然后不能整除一定是有n-n/K*K个长度为n/K+1的数字

先二分答案排名,枚举起始位置,考虑一个贪心的做法,假如当前能够放一个长度为n/K+1的就立刻放,这样能够保证最优

why?放n/K+1和n/K的区别相当于多往前走了1步,但是多用了一组n/K+1,假如走n/K在未来某一决策能够走n/K+1,那么当前走n/K+1只需付出少用一组就可以拉回同一起跑线。其实也就是具有决策包容性

 

#include
#include
#include
#include
#include
#include
using namespace std;const int _=1e2;const int maxn=2*2e5+_;int n,K,U;char ss[maxn];int sa[maxn],Rank[maxn];namespace SA{ int Rsort[maxn],tt[maxn]; void getsa(int n,int m) { for(int i=1;i<=n;i++)Rank[i]=ss[i]-'0'; memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=n;i++)Rsort[Rank[i]]++; for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1]; for(int i=n;i>=1;i--)sa[Rsort[Rank[i]]--]=i; int ln=1,p=0; while(p
0)tt[++k]=sa[i]-ln; memset(Rsort,0,sizeof(Rsort)); for(int i=1;i<=n;i++)Rsort[Rank[tt[i]]]++; for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1]; for(int i=n;i>=1;i--)sa[Rsort[Rank[tt[i]]]--]=tt[i]; for(int i=1;i<=n;i++)tt[i]=Rank[i]; p=1;Rank[sa[1]]=1; for(int i=2;i<=n;i++) { if(tt[sa[i]]!=tt[sa[i-1]]||tt[sa[i]+ln]!=tt[sa[i-1]+ln])p++; Rank[sa[i]]=p; } m=p;ln*=2; } } void GetTrueRank(int n) { int p=0; for(int i=1;i<=2*n-1;i++) if(sa[i]<=n)Rank[sa[i]]=Rank[sa[i]+n]=++p; for(int i=1;i<=n;i++)sa[Rank[i]]=i; } void main(int n){getsa(2*n-1,15);GetTrueRank(n);}}namespace PRINT{ void main(int ans,int len) { int st=sa[ans]; for(int i=1;i<=len;i++)putchar(ss[i+st-1]); puts(""); }}namespace SOL1{ void main() { int ans=(1<<30); for(int i=1;i<=U;i++) { int num=0,tt=0; for(int j=1;j<=K;j++) num=max(num,Rank[i+tt]),tt+=U; ans=min(ans,num); } PRINT::main(ans,U); }}namespace SOL2{ int calc(int em) { int mmax=0; for(int i=1;i<=U+1;i++) { int p=i,num=0; for(int j=1;j<=K;j++) { if(Rank[p]<=em)p+=U+1,num++; else p+=U; if(p>=i+n-1)break; } mmax=max(mmax,num); } return mmax; } void main() { int res=n-U*K; int el=1,er=n,em,ans; while(el<=er) { em=(el+er)/2; if(calc(em)>=res) { er=em-1; ans=em; } else el=em+1; } PRINT::main(ans,U+1); }}int main(){ scanf("%d%d%s",&n,&K,ss+1); U=n/K; for(int i=1;i

 

转载于:https://www.cnblogs.com/AKCqhzdy/p/10622132.html

你可能感兴趣的文章
java环境搭建个人注意
查看>>
C#基础类与接口的选择
查看>>
floating-camera
查看>>
mips gnu工具使用
查看>>
[javascript]event属性
查看>>
FTP操作(FTPClient)
查看>>
php防sql注入、xss
查看>>
数电碎片
查看>>
JavaBean的实例--邮件发送JavaBean:基于Javax.mail
查看>>
java遍历集合
查看>>
D. Renting Bikes 二分
查看>>
csharp C#数字字符串排序orderby的问题解决
查看>>
【转】LUA内存分析
查看>>
【转】Android studio安装与配置
查看>>
作为程序员的你,一年看几本技术相关的书
查看>>
[BZOJ 2738] 矩阵乘法 【分块】
查看>>
Grid move
查看>>
docker异常问题解决
查看>>
关于LR中的EXTRARES
查看>>
专业实训题目需求分析
查看>>