●BZOJ 4278 [ONTAK2015]Tasowanie

题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=4278

题解:

把两个串连接起来,用一个大数连接(必须要用大数)。
倍增算法求出后缀排名。
然后两个指针指向A,B串,每次比较两个后缀的大小,
优先取出小的那个后缀的首字母,然后对应指针向后移动一位。

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 450000
#define filein(x) freopen(#x".in","r",stdin);
#define fileout(x) freopen(#x".out","w",stdout);
using namespace std;
int sa[MAXN],rak[MAXN],hei[MAXN];
int A[MAXN],B[MAXN],T[MAXN];
int LA,LB;
void build(int N,int M){
	static int cc[MAXN],ta[MAXN],tb[MAXN],*x,*y,h,p;
	x=ta; y=tb; h=0; T[N]=-1;
	for(int i=0;i<M;i++) cc[i]=0;
	for(int i=0;i<N;i++) cc[x[i]=T[i]]++;
	for(int i=1;i<M;i++) cc[i]+=cc[i-1];
	for(int i=N-1;i>=0;i--) sa[--cc[x[i]]]=i;
	for(int k=1;p=0,k<N;k<<=1){
		for(int i=N-k;i<N;i++) y[p++]=i;
		for(int i=0;i<N;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
		for(int i=0;i<M;i++) cc[i]=0;
		for(int i=0;i<N;i++) cc[x[y[i]]]++;
		for(int i=1;i<M;i++) cc[i]+=cc[i-1];
		for(int i=N-1;i>=0;i--) sa[--cc[x[y[i]]]]=y[i];
		swap(x,y); y[N]=-1; x[sa[0]]=0; M=1;
		for(int i=1;i<N;i++)
			x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?M-1:M++;
		if(M>=N) break;
	}
	for(int i=0;i<N;i++) rak[sa[i]]=i;
	for(int i=0,j;i<N;i++){
		if(h) h--;
		if(rak[i]){
			j=sa[rak[i]-1];
			while(T[i+h]==T[j+h]) h++;
		}
		hei[rak[i]]=h;
	}
}
void solve(){
	int i=0,j=0,ii,jj,h;
	while(i<LA&&j<LB){
		ii=i; jj=LA+1+j;
		if(rak[ii]<rak[jj]) printf("%d ",A[i++]);
		else printf("%d ",B[j++]);
	}
	while(i<LA) printf("%d ",A[i++]);
	while(j<LB) printf("%d ",B[j++]);
}
int main()
{
	int N; scanf("%d",&LA);
	for(int i=0;i<LA;i++) scanf("%d",&A[i]),T[i]=A[i];
	T[LA]=1001; scanf("%d",&LB);
	for(int i=0;i<LB;i++) scanf("%d",&B[i]),T[LA+1+i]=B[i];
	N=LA+LB+1;
	build(N,1005);
	solve();
	return 0;
}
时间: 2024-08-30 11:26:19

●BZOJ 4278 [ONTAK2015]Tasowanie的相关文章

【BZOJ4278】[ONTAK2015]Tasowanie 后缀数组

[BZOJ4278][ONTAK2015]Tasowanie Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input 第一行包含一个正整数n(1<=n<=200000),表示A串的长度. 第二行包含n个正整数,其中第i个数表示A[i](1<=A[i]<=1000). 第三行包含一个正整数m(1<=m<=200000),表示B串的长度. 第四行包含m个正整数,其中第i个数表示B[i](1<=B[

bzoj4278: [ONTAK2015]Tasowanie

stl::sort实现的后缀数组,超级慢. 变量名打错好几个导致WA好几次. http://www.lydsy.com/JudgeOnline/problem.php?id=4278 /************************************************************** Problem: 4278 User: 1349367067 Language: C++ Result: Accepted Time:7900 ms Memory:13776 kb ***

BZOJ 4245: [ONTAK2015]OR-XOR 贪心

4245: [ONTAK2015]OR-XOR Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 567  Solved: 312[Submit][Status][Discuss] Description 给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m].请求出总费用的最小值. Input 第一行包含

BZOJ 4245 ONTAK2015 OR-XOR

题目大意:给定一个长度为n的序列,要求分成m段,使得每段异或和的或值最小 求出前缀异或和后从大到小按位确定,如果某一位上有至少m个数是0且第n个数是0,那么这一位就可以是0,同时将所有是1的数字标记为不可选 时间复杂度O(nlogai) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 using namespace s

BZOJ 4276: [ONTAK2015]Bajtman i Okr?g?y Robin

最大权值匹配,贪心匈牙利即可. 检查一些人是否能被全部抓住可以采用左端点排序,右端点优先队列处理. By:大奕哥 #include<bits/stdc++.h> using namespace std; const int N=5005; struct node{ int l,r,c; bool operator <(const node &b)const{ return c>b.c; } }p[N]; int match[N],ans,n; bool v[N]; bool

bzoj 4276: [ONTAK2015]Bajtman i Okr?g?y Robin【线段树+最大费用最大流】

--因为T点忘记还要+n所以选小了所以WA了一次 注意!题目中所给的时间是一边闭一边开的区间,所以读进来之后先l++(或者r--也行) 线段树优化建图,很神.(我记得还有个主席树优化建树的?)首先考虑暴力建图:s向每个强盗i连(s,i,1,c[i]),每个时间j向t连(j,t,1,0),每个强盗向所有他的时间j连边(i,j,1,0),然而这样显然是会TLE的. 所以考虑向区间连边,建一颗线段树,每个区间向它的两个子节点连费用0流量inf的边,叶节点向t(注意开大!)连费用0流量1的边限制"你在每

BZOJ.4298.[ONTAK2015]Bajtocja(Hash 启发式合并)

题目链接 \(Description\) 给定d张无向图,每张图都有n个点.一开始,在任何一张图中都没有任何边. 接下来有m次操作,每次操作会给出a,b,k,意为在第k张图中的点a和点b之间添加一条无向边. 你需要在每次操作之后输出有序数对(a,b)的个数,满足1≤a,b≤n,且a点和b点在d张图中都连通. d<=200,n<=5000,m<=1000000 \(Solution\) 我们需要知道的只是每对点之间是否连通,即在同一张图所属的连通块是否一样 于是我们对每个点在d张图中所属的

【BZOJ-4278】Tasowanie 后缀数组 + 归并

4278: [ONTAK2015]Tasowanie Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 164  Solved: 80[Submit][Status][Discuss] Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input 第一行包含一个正整数n(1<=n<=200000),表示A串的长度. 第二行包含n个正整数,其中第i个数表示A[i](1<=A[i]

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什