zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:寿司(暴力)

    题目描述

    小$c$是一名$oier$。最近,他发现他的数据结构好像学傻了。因为他在刷题时碰到了一道傻逼数据结构题,强行使用了平衡树来解决,卡着时间$AC$。为此,他被狠狠地嘲讽了一番。于是,小$c$找了大量的数据结构题来做。

    昨天,小$c$正在吃寿司,突然发现许多盘寿司围成了一个圆圈,这些寿司中有红色的也有蓝色的。由于小$c$看交错的颜色非常不爽,想通过一些操作,使得所有的红色寿司形成了一块连续的区域,蓝色的寿司也形成了一块连续的区域。如果小$c$每次只可以交换相邻的两盘寿司,那么最少需要多少步才可以达到小$c$的要求呢?由于他做题做多了,脑袋已经有点不清醒了,于是这个问题就交给你了。


    输入格式

    第一行一个数$T$,表示数据组数。
    接下来$T$行,每行一行由$B$和$R$组成的字符串,$B$表示蓝色,$R$表示红色。第$i$个字符描述顺时针数第$i$盘寿司的颜色。注意,最后一盘寿司和第$1$盘寿司是相邻的。


    输出格式

    对于每组数据,输出一行表示最小的交换次数。


    样例

    样例输入

    1
    BBRBBRBBBRRR

    样例输出

    5


    数据范围与提示

    样例说明:

    以下说明交换的步骤:
    交换位置$2$、位置$3$上的寿司;
    交换位置$1$、位置$2$上的寿司;
    交换位置$6$、位置$7$上的寿司;
    交换位置$7$、位置$8$上的寿司;
    交换位置$8$、位置$9$上的寿司;

    数据范围:

    $Tleqslant 10$

    $nleqslant 1,000,000$


    题解

    算法一:

    爆搜,枚举所有走法。可以获得$0$到$20$分不等。

    算法二:

    注意到每种状态实际上是可以压缩的。所以搜索的时候对于较小的数据把状态记录下来,用最小表示法去个重,对于稍大的数据可以用$IDA∗$搜索,对每个状态进行估价来进行加速。可以获得$20$到$40$分不等。

    算法三:

    将环上的问题转化为序列上,我们只需要将环复制一遍即可转化为序列。

    那么,考虑这样一个问题,对于最优解,一定存在一个点使得所有的交换都不经过这个点(它的左右不交换),下面简称这个点为断点。

    这样我们就可以枚举断点,答案即为把每个$B$挪到两端,反之同理。

    然后在进行统计答案,比较每一个断点哪个最优。

    现在来简单的证明一下断点的存在,来脑补一个环,环上面有很多$R$,我们肯定要将所有的$R$都撸到一起,而这时候,肯定存在“最下面一个点”作为底端,而在撸的时候肯定不会经过这个点。

    时间复杂度:$Theta (n^2)$。

    期望得分:$40$分。

    算法四:

    考虑决策的单调性问题,上面$Theta (n^2)$的算法中,我们需要再枚举一个点,这个点左端的$R$都移向左端,右端的都移向右端,那么就满足了一个$igcup$型函数。

    显然可以进行三分求解。

    那么当前枚举的区间的代价怎么求呢?

    我们需要开五个数组:

      $alpha.slft[i]$:表示将点$i$左侧所有的$R$都挪到最左端所要付出的代价,而每个$R$挪到最左端的代价就是它左端的$B$的数量。

      $eta.srht[i]$:表示将点$i$右侧所有的$R$都挪到最右端所要付出的代价。

      $chi.blft[i]$:表示点$i$左侧有几个$B$,可以感性的理解为$B$的左缀和。

      $delta.brht[i]$:表示点$i$右侧有几个$B$,可以感性的理解为$B$的右缀和。

      $epsilon.rlft[i]$:表示点$i$左侧有几个$R$,可以感性的理解为$R$的前缀和

    下面我只讲当前区间$[L,R]$下,将点$V$左侧的$R$都移到$L$所要付出的代价,反之同理:

      先写出来式子:$slft[V]-slft[L-1]-blft[L-1] imes (rlft[V]-rlft[L-1])$。

      来解释一下式子:

      $slft[V]-slft[L-1]$的含义为将$[L,V]$区间中所有的$R$移到最左端所要付出的代价,不过显然我们并不用把他们都移到左端,而是将其移动到$L$,那么我们不需要付出的代价就为$1$到$L$之间的$B$乘上$L$到$V$之间的$R$,即为$blft[L-1] imes (rlft[V]-rlft[L-1])$。

    时间复杂度:$Theta (nlog_{frac{3}{2}}n)$。

    期望得分:$65$分。

    算法五:

    我们还会发现这样一个问题,在断点不断右移的时候,当前状态的最有决策点肯定在上衣状态的最优决策点的右侧,这样复杂度就成了线性的了。

    时间复杂度:$Theta (n)$。

    期望得分:$100$分。


    代码时刻

    $Theta (nlog_{frac{3}{2}}n)$算法:

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    char ch[4000001];
    long long slft[4000001],srht[4000001],blft[4000001],brht[4000001],rlft[4000001];
    long long ans;
    long long minn(int x,int y,int z){return min(x,min(y,z));}
    long long judge(int l,int v,int r)
    {return slft[v]-slft[l-1]-blft[l-1]*(rlft[v]-rlft[l-1])+srht[v+1]-srht[r+1]-brht[r+1]*(rlft[r]-rlft[v]);}//计算答案
    long long _doudou(int l,int r)//三分
    {
    	int flagl=l,flagr=r;
    	while(r-l>2)
    	{
    		int midl=(r-l+1)/3+l;
    		int midr=(r-l+1)*2/3+l;
    		if(judge(flagl,midl,flagr)>judge(flagl,midr,flagr))l=midl;
    		else r=midr;
    	}
    	return minn(judge(flagl,l+1,flagr),judge(flagl,l,flagr),judge(flagl,r,flagr));
    }
    void pre_work()//清空
    {
    	for(int i=1;i<=n;i++)ch[n+i]=ch[i];
    	blft[0]=slft[0]=rlft[0]=srht[2*n+1]=brht[2*n+1]=0;
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%s",ch+1);
    		ans=200209230020020923;
    		n=strlen(ch+1);
    		pre_work();
    		for(int i=1;i<=2*n;i++)
    		{
    			blft[i]=blft[i-1];
    			slft[i]=slft[i-1];
    			rlft[i]=rlft[i-1];
    			if(ch[i]=='B')blft[i]++;
    			else
    			{
    				rlft[i]++;
    				slft[i]+=blft[i];
    			}
    		}
    		for(int i=2*n;i;i--)
    		{
    			brht[i]=brht[i+1];
    			srht[i]=srht[i+1];
    			if(ch[i]=='B')brht[i]++;
    			else srht[i]+=brht[i];
    		}
    		for(int i=1;i<=n;i++)
    			ans=min(ans,_doudou(i,i+n-1));
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    $Theta (n)$算法:

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    char ch[4000001];
    long long slft[4000001],srht[4000001],blft[4000001],brht[4000001],rlft[4000001];
    long long ans;
    long long judge(int l,int v,int r)
    {return slft[v]-slft[l-1]-blft[l-1]*(rlft[v]-rlft[l-1])+srht[v+1]-srht[r+1]-brht[r+1]*(rlft[r]-rlft[v]);}
    void pre_work()
    {
    	for(int i=1;i<=n;i++)ch[n+i]=ch[i];
    	blft[0]=slft[0]=rlft[0]=srht[2*n+1]=brht[2*n+1]=0;
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%s",ch+1);
    		ans=200209230020020923;
    		n=strlen(ch+1);
    		pre_work();
    		for(int i=1;i<=2*n;i++)
    		{
    			blft[i]=blft[i-1];
    			slft[i]=slft[i-1];
    			rlft[i]=rlft[i-1];
    			if(ch[i]=='B')blft[i]++;
    			else
    			{
    				rlft[i]++;
    				slft[i]+=blft[i];
    			}
    		}
    		for(int i=2*n;i;i--)
    		{
    			brht[i]=brht[i+1];
    			srht[i]=srht[i+1];
    			if(ch[i]=='B')brht[i]++;
    			else srht[i]+=brht[i];
    		}
    		int lft=1;
    		for(int i=1;i<=n;i++)
    		{
    			while(lft!=n+i&&judge(i,lft,i+n-1)>=judge(i,lft+1,i+n-1))lft++;
    			ans=min(ans,judge(i,lft,i+n-1));
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    rp++

  • 相关阅读:
    PAT (Advanced Level) 1060. Are They Equal (25)
    PAT (Advanced Level) 1059. Prime Factors (25)
    PAT (Advanced Level) 1058. A+B in Hogwarts (20)
    PAT (Advanced Level) 1057. Stack (30)
    PAT (Advanced Level) 1056. Mice and Rice (25)
    PAT (Advanced Level) 1055. The World's Richest (25)
    PAT (Advanced Level) 1054. The Dominant Color (20)
    PAT (Advanced Level) 1053. Path of Equal Weight (30)
    PAT (Advanced Level) 1052. Linked List Sorting (25)
    PAT (Advanced Level) 1051. Pop Sequence (25)
  • 原文地址:https://www.cnblogs.com/wzc521/p/11246907.html
Copyright © 2011-2022 走看看