zoukankan      html  css  js  c++  java
  • 【vijos1900】 学姐吃寿司

    https://vijos.org/p/1900 (题目链接)

    题意

      给出一个01环,问最少经过多少次相邻互换使得所有的0聚在一坨,所有的1聚在一坨。

    Solution

      源自:LCF Solution

      一般环上的问题都要把序列复制一遍,然后转成了序列上的问题。这道也不例外。

      经过观察后我们“显然”可以得到一个结论:对于最优解,定有断点使得所有的交换都不经过这个点。因为如果所有相邻的位置都交换了一次,相邻的位置都交换了一次那么这些操作并没有改变这个环的形态,也就是没有任何作用完全可以直接去掉。(然而LCF讲题翻车,这个证明显然是错误的,在不同的时间交换两个相邻的位置最终态并不会一样→_→。然而我也会证,只是感觉很正确)

      于是,我们就可以枚举断点,然后就转变为了一个序列了。我们的目的就变成了使0全部靠边。然后可以预处理出每个0移动到左边界需要多少步,右边界需要多少步。发现对于一个序列,肯定是存在一条分界线使得左边一部分0往左靠,右边一部分0往右靠,当断点顺时针移动的时候,分界点显然不会逆时针移动。于是这玩意儿是有单调性的,弄一个单调指针扫一扫就可以了。

    细节

      数组开大两倍

    代码

    // vijos1900
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 1e18
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=2000010;
    int a[maxn],sum[maxn];
    char ch[maxn];
    
    int main() {
    	int T;scanf("%d",&T);
    	for (int cas=1;cas<=T;cas++) {
    		scanf("%s",ch+1);
    		int n=strlen(ch+1);
    		for (int i=1;i<=n;i++) {
    			if (ch[i]=='B') a[i]=0;
    			else a[i]=1;
    		}
    		for (int i=n+1;i<=n*2;i++) a[i]=a[i-n];
    		for (int i=1;i<=n*2;i++) sum[i]=a[i]+sum[i-1];
    		LL p=1,ans=inf,L=0,R=0,lnum=0,rnum=0;
    		for (int i=1;i<=n;i++) if (a[i]==0) R+=sum[n]-sum[i-1],rnum++;
    		for (int s=1;s<=n;s++) {
    			int t=s+n-1;
    			if (s!=1) {
    				if (a[s-1]==0) lnum--;
    				if (a[s-1]==1) L-=lnum;
    				if (a[t]==0) rnum++;
    				if (a[t]==1) R+=rnum;
    			}
    			for (p;p<=t+1;p++) if (a[p]==0) {
    					if (sum[p-1]-sum[s-1]>sum[t]-sum[p]) break;
    					L+=sum[p-1]-sum[s-1];
    					R-=sum[t]-sum[p];
    					lnum++;rnum--;
    				}
    			ans=min(ans,L+R);
    		}
    		printf("Case #%d: %lld
    ",cas,ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    01-Git 及其可视化工具TortoiseGit 的安装和使用
    IntelliJ IDEA中Warning:java:源值1.5已过时, 将在未来所有发行版中删除
    JVM学习笔记四_垃圾收集器与内存分配策略
    JVM学习笔记三_异常初步
    CentOs7 图形界面和命令行界面切换
    基本概念一
    JVM学习笔记二_对象的创建、布局和定位
    JVM学习笔记一_运行时数据区域
    个人阅读作业二
    软件工程随笔
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6028508.html
Copyright © 2011-2022 走看看