zoukankan      html  css  js  c++  java
  • 【BZOJ2882】工艺(后缀数组一眼题)

    点此看题面

    大致题意: 给定一个(n)个数的环,让你把它断开,使得字典序最小。

    前言

    这道题在洛谷上只是道蓝题,大概有什么其他做法吧。。。

    后缀数组

    一眼题。显然只要把原串复制一遍然后后缀排序即可。

    注意最后选择断开的位置应该是第一个小于等于(n)(SA_i),一开始智障了。。。

    代码

    #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 600000
    using namespace std;
    int n,a[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--]);pc(' ');}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    class SuffixArray
    {
    	private:
    		int l,SA[N+5],rk[N+5],p[N+5],t[N+5];
    		I void Sort(CI S)//基数排序
    		{
    			RI i;for(i=0;i<=S;++i) t[i]=0;for(i=1;i<=l;++i) ++t[rk[i]];
    			for(i=1;i<=S;++i) t[i]+=t[i-1];for(i=l;i;--i) SA[t[rk[p[i]]]--]=p[i];
    		}
    		I void GetSA()//后缀排序
    		{
    			RI i;for(i=1;i<=l;++i) rk[p[i]=i]=a[i];
    			RI k,t=0,S=N;for(Sort(S),k=1;t^l;k<<=1,S=t)
    			{
    				for(t=0,i=1;i<=k;++i) p[++t]=l-k+i;for(i=1;i<=l;++i) SA[i]>k&&(p[++t]=SA[i]-k);
    				for(Sort(S),i=1;i<=l;++i) p[i]=rk[i];
    				for(rk[SA[1]]=t=1,i=2;i<=l;++i) rk[SA[i]]=
    					(p[SA[i-1]]^p[SA[i]]||p[SA[i-1]+k]^p[SA[i]+k])?++t:t;
    			}
    		}
    	public:
    		I int GetID(CI x)
    		{
    			l=x,GetSA();for(RI i=1;i<=l;++i) if(SA[i]<=n) return SA[i];//求出第一个小于等于n的SA
    		}
    }S;
    int main()
    {
    	RI i,j,k;for(F.read(n),i=1;i<=n;++i) F.read(a[i]),a[n+i]=a[i];//复制一遍
    	for(k=S.GetID(n<<1),i=0;i^n;++i) F.write(a[k+i]);return F.clear(),0;//输出答案
    }
    
  • 相关阅读:
    找水王
    环状二维数组最大子数组和
    用户模板
    课堂作业-电梯调度
    书店折扣问题
    《软件工程》读后感
    首尾相连的二维数组最大子数组求和
    梦断代码读后感(二)
    返回一个整数数组中最大子数组的和之测试
    首尾相连的一位数组最大子数组和
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2882.html
Copyright © 2011-2022 走看看