首页 > 代码库 > bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&&bzoj1692[Usaco2007 Dec]队列变换*
bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&&bzoj1692[Usaco2007 Dec]队列变换*
bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换
bzoj1692[Usaco2007 Dec]队列变换
题意:
有一个奶牛队列。每次可以在原来队列的首端或是尾端牵出一头奶牛,把她安排到新队列的尾部,然后对剩余的奶牛队列重复以上的操作,直到所有奶牛都被插到了新的队列里。这样得到的队列,就是FJ拉去登记的最终的奶牛队列。 求对于给定的奶牛们的初始位置,计算出可能得到的字典序最小的队列。队列大小≤30000。
题解:
有一个结论:如果当前队列中的队首元素不等于队尾元素,则选小的那一边;否则选以右端点为下标的前缀和以左端点为下标的后缀中较小的那边。对于比较前缀后缀,正解是后缀数组,然而本弱偷懒写了个哈希,比较两个字符串的大小只要二分LCP,然后比较LCP的下一个字符即可。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define inc(i,j,k) for(int i=j;i<=k;i++) 6 #define maxn 30010 7 #define ll unsigned long long 8 #define num 233 9 using namespace std; 10 11 inline int read(){ 12 char ch=getchar(); int f=1,x=0; 13 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} 14 while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar(); 15 return f*x; 16 } 17 ll hash1[maxn],hash2[maxn],mi[maxn]; int l,r,n,tot; char name1[maxn],name2[maxn],ans[maxn]; 18 bool cmp(int x,int y){ 19 int l=1,r=min(n-x+1,y),z=0; 20 while(l<=r){ 21 int mid=(l+r)>>1; 22 if(hash1[x+mid-1]-hash1[x-1]*mi[mid]==hash2[n-y+1+mid-1]-hash2[(n-y+1)-1]*mi[mid])z=mid,l=mid+1;else r=mid-1; 23 } 24 return name1[x+z]<=name2[n-y+1+z]; 25 } 26 int main(){ 27 n=read(); inc(i,1,n)scanf("%s",name1+i); inc(i,1,n)name2[i]=name1[n-i+1]; mi[0]=1; 28 inc(i,1,n)hash1[i]=hash1[i-1]*num+name1[i],hash2[i]=hash2[i-1]*num+name2[i],mi[i]=mi[i-1]*num; 29 l=1; r=n; 30 while(l<r){ 31 if(name1[l]<name1[r])ans[++tot]=name1[l],l++; 32 else if(name1[l]>name1[r])ans[++tot]=name1[r],r--; 33 else if(cmp(l,r))ans[++tot]=name1[l],l++; 34 else ans[++tot]=name1[r],r--; 35 } 36 ans[++tot]=name1[l]; inc(i,1,tot){printf("%c",ans[i]); if(i%80==0)puts("");} return 0; 37 }
20161102
bzoj1640[Usaco2007 Nov]Best Cow Line 队列变换*&&bzoj1692[Usaco2007 Dec]队列变换*
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。