bzoj 4278 Tasowanie 后缀数组+贪心
题目大意
给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T.\(len \leq 200000\)
题解
我们从归并排序的角度去想,每次把两者之一较小的取出来
遇到相等的元素的时候,排序时取那个都是一样的.
但是在这道题中我们是求字典序最小,这就不一样了.
我们不能任意取,这一步的决策其实是由后面的数字的大小决定的
怎么说呢...
方法蕴藏在这三张图里了,自己去悟吧。
黑色箭头表示选取,黑色圆圈表示确定选取序列的理由.
迭代第一次

迭代第二次

迭代第三次

剩下的略...
这个东西我们可以用后缀数组(lcp)来维护
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch=='-')ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
const int maxn = 410010;
int a[maxn],b[maxn],c[maxn];
int wa[maxn],wb[maxn],ws[maxn];
int sa[maxn],rank[maxn],height[maxn];
inline bool cmp(int *r,int i,int j,int l){
return r[i] == r[j] && r[i+l] == r[j+l];
}
void da(int *r,int n,int m){
int i,j,p,*x = wa,*y = wb;
for(i=0;i<m;++i) ws[i] = 0;
for(i=0;i<n;++i) ws[x[i] = r[i]]++;
for(i=1;i<m;++i) ws[i] += ws[i-1];
for(i=n-1;i>=0;--i) sa[--ws[x[i]]] = i;
for(j=1,p=1;p<n;j<<=1,m=p){
for(p=0,i=n-j;i<n;++i) y[p++] = i;
for(i=0;i<n;++i) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i=0;i<m;++i) ws[i] = 0;
for(i=0;i<n;++i) ws[x[y[i]]]++;
for(i=1;i<m;++i) ws[i] += ws[i-1];
for(i=n-1;i>=0;--i) sa[--ws[x[y[i]]]] = y[i];
for(swap(x,y),p=1,i=1,x[sa[0]] = 0;i<n;++i)
x[sa[i]] = cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;
}
}
void get_h(int *r,int n){
int i,j,k=0;for(i=1;i<=n;++i) rank[sa[i]] = i;
for(i=0;i<n;height[rank[i++]] = k)
for(k ? --k : 0,j = sa[rank[i]-1];r[i+k] == r[j+k];++k);
}
int loger[maxn],minn[maxn][22];
void pre(int *r,int n){
loger[1] = 0;
for(int i=2;i<=n;++i){
loger[i] = loger[i-1];
if( (1 << loger[i]+1 ) == i) ++loger[i];
}
for(int i=n;i>=1;--i){
minn[i][0] = r[i];
for(int j=1;(i + (1<<j) - 1) <= n;++j){
minn[i][j] = min(minn[i][j-1],minn[i+(1<<j-1)][j-1]);
}
}
}
int lcp(int s,int t){
s = rank[s];t = rank[t];
if(s+1 > t) swap(s,t);++s;
int k = loger[t-s+1];
return min(minn[s][k],minn[t-(1<<k)+1][k]);
}
int n,m,len;
inline bool order(int i,int j){
int k = lcp(i,j);
int x = (i+k) == n ? 0x7f7f7f7f : c[i+k];
int y = (j+k) == len ? 0x7f7f7f7f : c[j+k];
return x <= y;
}
int q[maxn];
int main(){
read(n);
for(int i=0;i<n;++i){
read(a[i]);
c[i] = a[i];
}c[n] = 1005;
read(m);
for(int i=0;i<m;++i){
read(b[i]);
c[n+i+1] = b[i];
}len = n+m+1;c[len] = 0;
da(c,len+1,1010);
get_h(c,len);
pre(height,len);
int i=0,j=0,k=0;
while(i < n && j < m){
int x = order(i,j+n+1);
if(x == 1) q[k++] = a[i++];
else q[k++] = b[j++];
}
while(i < n) q[k++] = a[i++];
while(j < m) q[k++] = b[j++];
for(i=0;i<k;++i) printf("%d ",q[i]);
getchar();getchar();
return 0;
}
bzoj 4278 Tasowanie 后缀数组+贪心的更多相关文章
- bzoj 4278 Tasowanie —— 后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4278 每次取两个后缀中字典序较小的那个的首字符: 注意超出去的部分是 inf 而不是 0,因 ...
- BZOJ 4278: [ONTAK2015]Tasowanie 后缀数组 + 贪心 + 细节
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin ...
- BZOJ4278 [ONTAK2015]Tasowanie[后缀数组+贪心]
题目 求两数组归并后的数组最小字典序排列. 嘛,可能本人在贪心这块还是太弱了(或者说什么都弱),如果不知道是字符串题估计也想不起来用sa. 显然看得出归并时字典序小的那个数组先往里面加,这就是要比较两 ...
- BZOJ 4278 [ONTAK2015]Tasowanie (后缀数组)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4278 题解: 居然把后缀数组写成n^2的..我真厉害.. 想了无数种方法,最后发现就是 ...
- BZOJ 4278: [ONTAK2015]Tasowanie (后缀数组 / 二分+hash)
直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门- 但是本蒟蒻不会后缀数组 Upd:Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2 ...
- [BZOJ 1692] [Usaco2007 Dec] 队列变换 【后缀数组 + 贪心】
---恢复内容开始--- 题目链接:BZOJ - 1692 题目分析 首先,有个比较简单的贪心思路:如果当前剩余字符串的两端字母不同,就选取小的字母,这样显然是正确的. 然而若两端字母相同,我们怎么选 ...
- BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1383 Solved: 582[Submit][St ...
- 【BZOJ】1692 & 1640: [Usaco2007 Dec]队列变换(后缀数组+贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=1692 http://www.lydsy.com/JudgeOnline/problem.php?id ...
- 【BZOJ-4278】Tasowanie 后缀数组 + 归并
4278: [ONTAK2015]Tasowanie Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 164 Solved: 80[Submit][S ...
随机推荐
- 想全面理解JWT?一文足矣!
有篇关于JWT的文章,叫"JWT: The Complete Guide to JSON Web Tokens",写得全面细致.为了自己能更清晰理解并惠及更多人,我把它大致翻译了过 ...
- 查看mysql 的存储过程定义
查询数据库中的存储过程 方法一: select `name` from mysql.proc where db = 'your_db_name' and `type` = 'PROCEDURE' 方法 ...
- 在tomcat中用jndi配置数据源启动java web程序
1.在web.xml中添加: <resource-ref> <res-ref-name>jdbc/MTSDB</res-ref-name> <re ...
- WEB消息推送-comet4j
一.comet简介: comet :基于 HTTP长连接的“服务器推”技术,是一种新的 Web 应用架构.基于这种架构开发的应用中,服务器端会主动以异步的方式向客户端程序推送数据,而不需要客户端显式的 ...
- linux jdk 安装另一种方法
linux 7.2 安装 jdk方法: (1). 以root用户登录linux系统, 应用Xmanager把文件拷贝到linux 系统的根目录. (2). 进入opt/software建立jvm文件夹 ...
- 【BZOJ4399】魔法少女LJJ 线段树合并
[BZOJ4399]魔法少女LJJ Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的 ...
- 【BZOJ2989】数列 kd-tree
[BZOJ2989]数列 Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[y]| ...
- 之前博客中的代码都放到github上
之前一直把代码托管在taocode上,现在已经不能用了,所以把代码整理了一下,统一都放在gibhub上了. LALR(1)语法分析生成器:https://github.com/kiven-li/xby ...
- 我们计划为EasyDSS定制开发一款超低延时的EasyPlayer Flash播放器
现象 最近团队在做EasyDSS RTMP流媒体服务器开发的过程中,遇到了一个关于延时累积的问题,先大概描述一下过程: 在EasyRTMP Android进行长时间的RTMP推流压力测试,在EasyD ...
- OpenFileDialog对话框Filter属性(转)
OpenFileDialog对话框的Filter属性说明: 首先说明一个示例,分析一下Filter属性的构成:“ Excel文件|*.xls ”,前面的“Excel文件”成为标签,是一个可读的字符串, ...