zoukankan      html  css  js  c++  java
  • 【JZOJ1247】【洛谷P2870】队列变换【hash】【二分】【贪心】

    题目:

    题目链接:https://www.luogu.org/problem/P2870
    FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”。在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过。
    今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie、Sylvia、Dora,登记人员就把这支队伍登记为BSD)。登记结束后,组委会将所有队伍的登记名称按字典序升序排列,就得到了他们的出场顺序。
    FJ最近有一大堆事情,因此他不打算在这个比赛上浪费过多的时间,也就是说,他想尽可能早地出场。于是,他打算把奶牛们预先设计好的队型重新调整一下。
    FJ的调整方法是这样的:每次,他在原来队列的首端或是尾端牵出一头奶牛,把她安排到新队列的尾部,然后对剩余的奶牛队列重复以上的操作,直到所有奶牛都被插到了新的队列里。这样得到的队列,就是FJ拉去登记的最终的奶牛队列。
    接下来的事情就交给你了:对于给定的奶牛们的初始位置,计算出按照FJ的调整规则所可能得到的字典序最小的队列。


    思路:

    如果现在头和尾的字符不同,那么肯定选小的。
    如果相同,那么肯定将第二项和倒数第二项进行比较,选择较小的那一边。
    但是这样的时间复杂度是O(n2)O(n^2)的。
    不难发现,如果这个字符串的前ii项和后ii项相同,那么前i1i-1项和后i1i-1项也一定相同。所以这个满足单调性,我们可以二分它相同的长度,然后每次用hashhashcheckcheck
    得出前后相同的最大程度lenlen后,我们比较第len+1len+1项和倒数第len+1len+1项即可。这样的时间复杂度就是O(nlogn)O(nlog n)


    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ull;
    
    const int N=30010;
    const ull base=13331;
    ull hash[3][N],p[N];
    int n,a[N];
    char ch;
    
    void solve()
    {
    	for (int i=1,j=n,cnt=0;i<=j;)
    	{
    		int l=1,r=j-i+1,mid;
    		while (l<=r)
    		{
    			mid=(l+r)>>1;
    			if (hash[1][i+mid-1]-hash[1][i-1]*p[mid]==hash[2][j-mid+1]-hash[2][j+1]*p[mid]) l=mid+1;
    				else r=mid-1;
    		}
    		if (a[i+r]>a[j-r]) putchar(a[j--]+'A'-1);
    			else putchar(a[i++]+'A'-1);
    		cnt++;
    		if (!(cnt%80)) putchar(10);
    	}
    }
    
    int main()
    {
    	//freopen("ans.txt","w",stdout);
    	scanf("%d",&n);
    	p[0]=1;
    	for (int i=1;i<=n;i++)
    	{
    		while (ch=getchar()) if (ch>='A' && ch<='Z') break;
    		a[i]=ch-'A'+1;
    		p[i]=p[i-1]*base;
    	}
    	for (int i=1;i<=n;i++)
    		hash[1][i]=hash[1][i-1]*base+a[i];
    	for (int i=n;i>=1;i--)
    		hash[2][i]=hash[2][i+1]*base+a[i];
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    每天多一点之一个新的责任
    每天多一点之XML规则
    每天多一点之flush()
    Response.Redirect() 跳转中的ThreadAbortException
    IIS中的SSL Certificate 证书配置
    AD FS Setup Guide
    C#中静态方法和实例方法的使用
    SQL中的数据的批量操作
    页面JavaScript文件优化
    C#中的Equals、RefrenceEquals和==的区别
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11997996.html
Copyright © 2011-2022 走看看