zoukankan      html  css  js  c++  java
  • 【BZOJ4278】[ONTAK2015] Tasowanie(后缀数组+贪心)

    点此看题面

    大致题意: 给定两个数字串,让你对它们进行归并得到一个字典序最小的新串。

    贪心

    一看完题面首先想到无脑贪心,优先选小的数。

    然后突然想到碰到两个一样的数该先选谁?于是无脑贪心就被(Hack)掉了。

    所以,我们来考虑有脑贪心。

    考虑先把两个串并起来后缀排序,则我们优先选择后缀排序中后缀排名较为靠前(即(rk)较小)的数即可。

    至于正确性我想应该显然。

    注意每个串最后要放一个大数(可以分别放上(1001)(1002)),不然样例都过不了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 200000
    using namespace std;
    int n,m,s[2*N+5];
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define pc(c) (C==E&&(clear(),0),*C++=c)
    		#define D isdigit(c=tc())
    		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    	public:
    		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    		Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
    		Tp I void write(Con Ty& x,Con char& y) {write(x),pc(y);}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    class SuffixArray//后缀数组
    {
    	private:
    		int n,SA[2*N+5],p[2*N+5],t[2*N+5];
    		I void Sort(CI S)
    		{
    			RI i;for(i=0;i<=S;++i) t[i]=0;for(i=1;i<=n;++i) ++t[rk[i]];
    			for(i=1;i<=S;++i) t[i]+=t[i-1];for(i=n;i;--i) SA[t[rk[p[i]]]--]=p[i];
    		}
    	public:
    		int rk[2*N+5];
    		I void GetSA(CI x,int *s)
    		{
    			RI i;for(n=x,i=1;i<=n;++i) rk[p[i]=i]=s[i];
    			RI k,t=0,S=1002;for(Sort(S),k=1;t^n;S=t,k<<=1)
    			{
    				for(t=0,i=1;i<=k;++i) p[++t]=n-k+i;
    				for(i=1;i<=n;++i) SA[i]>k&&(p[++t]=SA[i]-k);
    				for(Sort(S),i=1;i<=n;++i) p[i]=rk[i];
    				for(rk[SA[1]]=t=1,i=2;i<=n;++i)
    					rk[SA[i]]=(p[SA[i-1]]^p[SA[i]]||p[SA[i-1]+k]^p[SA[i]+k])?++t:t;
    			}
    		}
    }S;
    int main()
    {
    	RI i,j;for(F.read(n),i=1;i<=n;++i) F.read(s[i]);s[n+1]=1001;
    	for(F.read(m),i=1;i<=m;++i) F.read(s[n+1+i]);s[n+m+2]=1002;S.GetSA(n+m+2,s);
    	i=1,j=1;W(i<=n&&j<=m) F.write(S.rk[i]<S.rk[n+1+j]?s[i++]:s[n+1+(j++)],' ');//归并
    	W(i<=n) F.write(s[i]," 
    "[i==n]),++i;W(j<=m) F.write(s[n+1+j]," 
    "[j==m]),++j;//处理剩余部分
    	return F.clear(),0;
    }
    
  • 相关阅读:
    .NET 应用架构指导 V2 [1]
    MSSQL优化之————探索MSSQL执行计划
    删除代码中所有的空行
    微软企业库5.0学习笔记(一)企业库是什么?
    C# MP3操作类
    Microsoft Enterprise Library 5.0系列学习笔记【1】
    基于Asp.net的CMS系统We7架设实验(环境WIN7,SQL2005,.NET3.5)(初学者参考贴) 【转】
    C#中用ILMerge将所有引用的DLL和exe文件打成一个exe文件,有图解
    “Singleton”模式
    阅读技术类图书的思考
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4278.html
Copyright © 2011-2022 走看看