n2还要讲吗?提一下吧,毕竟考场上我也只能想到这个。

我的思路和下发的题解所讲的思路又不太一样。如果你不想看我的思路而想直接跟着正解走,可以直接从下面的分界线以下开始阅读。

我的想法也是化环为序列,枚举所有可能的n长的序列。(这个应该没人不知道吧?)

然后,我的思路是:对于每个序列,枚举j表示把所有的颜色聚集到位置j附近。

我们假设我们移动的颜色为1,而不动的颜色为0。那么我们现在需要聚集的数字是1。

最后的效果大概是00000111111111000这样的

对于一个位置,需要的变换总数是多少?

101010010(1)001011

假如我们需要把两边所有的1移动到带括号的1附近,所有数从左往右下标是1~16,这是j是10。

对于第4个1:(10-1)-8=1步

对于第3个1:(10-2)-5=3步

对于第2个1:(10-3)-3=4步

对于第1个1:(10-4)-1=5步

对于这些在分界线左边的1,观察上面的式子:被减数形成等差数列,减数是这个数字1所在的位置

等差数列求和可以O(1)搞定,而位置的求和可以用前缀和维护。

对于第6个1:13-(10+1)=2步

对于第7个1:15-(10+2)=3步

对于第8个1:16-(10+3)=3步

在分界线右边的这些1其实也同理,一个等差数列一个前缀和。

而括号里的那个10就是枚举的j,把它们提出来乘以个数很好算,剩下的就是以1为首项1为公比的等差数列了。

我这样是为了方便求,当然也可以不提出来,反正我的代码实现里是这样的。

规律大概找到了,把通式写出来就不难了吧。

特别的,如果你选中的j位置上是一个0,想把那些1移过来,会是这样的效果:

0000001111(0)110000

这肯定没完啊,它没连成一块。接下来的操作就很好想了:要么把左边的都右移,要么右边的左移。

额外的操作步数就是min(左边1的个数,右边1的个数)。

至于怎么O(1)找到一段上1的个数。。前缀和呗。

(我的代码中j的含义是整个序列的起点位置,i是数字1聚集的位置,和上面说的不同,注意区分)

(a[i]是[下标小于等于i的所有数字1的下标前缀和],c[i]是[下标小于等于i的所有数字1的个数前缀和])

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 int c[2000005],n,x[2000005],t;long long a[2000005],ans;
 5 #define r register
 6 inline void read(){
 7     r char ch=getchar();n=0;
 8     while(ch!='R'&&ch!='B')ch=getchar();
 9     while(ch=='R'||ch=='B')x[++n]=(ch=='R'?1:0),ch=getchar();
10 }
11 int main(){
12     scanf("%d",&t);
13     while(t--){
14         read();ans=(long long)1e15;
15         const r int nn=n,nnn=n*2;
16         for(r int i=1;i<=nn;++i)x[i+n]=x[i];
17         for(r int i=1;i<=nnn;++i)c[i]=c[i-1]+x[i],a[i]=a[i-1]+i*x[i];
18         for(r int i=1;i<=nnn;++i){
19             const r int mx=min(i,n);
20             for(r int j=max(i-n+1,1);j<=mx;++j){
21                 const r int ll=c[i-1]-c[j-1],rr=c[j+n-1]-c[i];
22                 ans=min(ans,(ll-rr)*i+a[j+n-1]+a[j-1]-a[i]-a[i-1]-(ll*(ll+1ll)+rr*(rr+1ll))/2+(x[i]?0:min(ll,rr)));
23                 //printf("%d %d %d %d %lld\n",i,j,ll,rr,(ll-rr)*i+a[j+n-1]+a[j-1]-a[i]-a[i-1]-(ll*(ll+1ll)+rr*(rr+1ll))/2+(x[i]?0:min(ll,rr)));
24             }
25         }
26         printf("%lld\n",ans);
27     }
28 }
给出考场上的40分代码

相关文章:

  • 2021-10-29
  • 2021-11-08
  • 2021-05-15
  • 2021-07-06
  • 2021-09-25
  • 2021-12-03
  • 2022-12-23
猜你喜欢
  • 2021-06-22
  • 2021-07-13
  • 2021-07-20
  • 2023-03-14
  • 2021-11-05
  • 2022-01-08
相关资源
相似解决方案