zoukankan      html  css  js  c++  java
  • BZOJ4532: [BeiJing2014 WinterCamp] 珠链

    Description

    Alex喜欢玩网络游戏,认为这是智力和体力的综合锻炼。在一次游戏活动中,他意外获得了一个传说中威力极其强大的法宝:珠链。 
    珠链,顾名思义,就是由许多小珠子串起来的一条链。珠子有很多种颜色。Alex听说过,只有将珠链打磨纯净,珠链才能发挥最大的威力。 
    纯净珠链是指这样的珠链:它可以分成若干个长度相等的段,使任何两段的任何相同位置的珠子的颜色均不同,相同位置指珠子在段内的相对位置相同;而且每段的长度以及划分的段数也是有规范的,Alex记得,每段包含的珠子数目必须在L到R之间,而且划分的段数不能少于S。 
    所谓打磨,就是从珠链的首和尾拿掉连续的若干个珠子。打磨后的纯净珠链的威力等于它的每个珠子具有的魔力值之和。一个珠子的魔力值只与它在打磨前的珠链中的位置有关。在查找和分析了大量实验数据以后,Alex发现珠子的魔力值等于珠子原来位置编号的约数个数! 
    兴奋不已的Alex想将珠链打磨成威力最大的纯净珠链。然而,马上要参加期末考试的Alex来不及计算了,你能否帮助Alex算出最大的威力值呢? 
     

    Input

    第一行是四个整数N, L, R, S。 
    第二行是一个长度等于N的字符串,表示Alex得到的珠链。字符串的第i个字符表示珠链的第i个珠子的颜色。相同字母表示相同颜色。珠子的位置从1编号到N。 
    1 ≤ N ≤ 500,000,1 ≤ L, R, S ≤ N, 0 ≤ R – L ≤ 10. 输入的字符串只包含大写和小写的英文字母。字母区分大小写。
     

    Output

    输出一行,表示打磨后的纯净珠链的最大威力值。如果无法打磨成满足要求的纯净珠链,输出 -1. 
     

    Sample Input

    7 2 3 2
    abcbcaa

    Sample Output

    15
    【样例解释】
    能够打磨出的合乎要求的纯净珠链有三种:bc/aa, abc/bca和bcb/caa。其中威力最大的是第三种,其威力值等于2+2+3+2+4+2 = 15。
    如果给出的珠链是纯净珠链,那么可以不打磨。纯净珠链必须能划分成不少于S个等长的段且每段长度在L到R之间。
     
    因为R-L+1<=10,所以我们可以枚举每一段的长度。
    对于“任何两段的任何相同位置的珠子的颜色均不同”,我们按模x分类,计算出每个位置上一个和它颜色相同的位置,那么一段珠子能包含的最左端点就是一个区间的最大值。
    然后滑动一下窗口即可。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=500010;
    int n,s,S[maxn],Q[maxn],ans=-1;
    int f[maxn],g[maxn],A[maxn],last[55];
    char str[maxn];
    int idx(char c) {return (c>='a'&&c<='z')?c-'a':c-'A'+26;}
    ll solve(int x) {
    	rep(i,0,x-1) {
    		for(int j=i;j<n;j+=x) f[j]=last[A[j]],last[A[j]]=j;
    		for(int j=i;j<n;j+=x) last[A[j]]=-1;
    	}
    	int l=1,r=0;
    	rep(i,0,n-1) {
    		while(l<=r&&f[Q[r]]<f[i]) r--;Q[++r]=i;
    		while(Q[l]<=i-x) l++;
    		if(i>=x-1) g[i-x+1]=f[Q[l]];
    	}
    	rep(i,0,x-1) {
    		l=i;
    		for(int j=i;j+x-1<n;j+=x) {
    			while(l<=g[j]) l+=x;
    			if(j-l>=(s-1)*x) ans=max(ans,S[j+x]-S[l]);
    		}
    	}
    }
    int main() {
    	int l,r;
    	memset(last,-1,sizeof(last));
    	n=read();l=read();r=read();s=read();
    	rep(i,1,n) for(int j=i;j<=n;j+=i) S[j]++;
    	rep(i,2,n) S[i]+=S[i-1];
    	scanf("%s",str);
    	rep(i,0,n-1) A[i]=idx(str[i]);
    	rep(i,l,r) solve(i);
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    Linux的进程线程及调度
    Linux-485收发切换延迟的解决方法
    FFmpeg内存IO模式(内存区作输入或输出)
    ffplay源码分析7-播放控制
    ffplay源码分析6-音频重采样
    ffplay源码分析5-图像格式转换
    ffplay源码分析4-音视频同步
    ffplay源码分析3-代码框架
    ffplay源码分析2-数据结构
    ffplay源码分析1-概述
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5392267.html
Copyright © 2011-2022 走看看