zoukankan      html  css  js  c++  java
  • Codeforces 1428F Fruit Sequences 乱搞计数

    Codeforces 1428F Fruit Sequences

    题意

    给一个长度为(n)(01)(s)(f(l,r))为区间([l,r])内最长连续(1)的个数,计算(sum_{i=1}^{n}sum_{j=i}^{n}f(i,j))

    (n le 5 cdot 10^5)

    分析

    (pre[i])为位置(i)之前连续(1)的个数,(suf[i])为位置(i)之后连续(1)的个数,例如(00111100)(pre[4]=2,suf[4]=3)

    (dp[i])(sum_{j=1}^{i}f(j,i+suf[i]-1)),如何计算(dp[i]):

    • 首先要加上(sum_{j=i-pre[i]+1}^{i}suf[j]),也就是包含位置(i)的一段连续(1)的贡献,可以用求和公式化简。
    • 再找到(i)之前最近的一个位置(j),且(suf[j]>pre[i]+suf[i]-1),若找不到则令(j=0),加上(dp[j]+(i-pre[i]-j)cdot (pre[i]+suf[i]-1))

    计算完(dp)数组后,再枚举端点(r),令(ans)加上(sum_{j=1}^{pre[i]}j),也就是(r)之前连续一段(1)的贡献,再类似的找到(r)之前最近的一个位置(j),且(suf[j]>pre[r]),若找不到则令(j=0),加上(dp[j]+(r-pre[r]-j)cdot pre[r])

    Code

    #include <bits/stdc++.h>
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    using namespace std;
    typedef long long ll;
    const int N=5e5+10;
    int n;
    int a[N];
    ll f[N];
    int pre[N],suf[N],st[N][20];
    void init(){
    	for(int i=1;i<=n;i++) st[i][0]=suf[i];
    	for(int j=1;(1<<j)<=n;j++){
    		for(int i=1;i+(1<<j)-1<=n;i++){
    			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
    		}
    	}
    }
    int qmx(int l,int r){
    	int k=(int)log2(r-l+1);
    	return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    int qy(int x,int num){
        int l=1,r=x;
        while(l<=r){
            int mid=l+r>>1;
            int cnt=qmx(mid,x);
            if(cnt>=num) l=mid+1;
            else r=mid-1;
        }
        return r;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
    
        for(int i=1;i<=n;i++){
            if(a[i]) pre[i]=pre[i-1]+1;
        }
        for(int i=n;i>=1;i--){
            if(a[i]) suf[i]=suf[i+1]+1;
        }
        init();
        for(int i=1;i<=n;i++) if(a[i]){
            f[i]=1ll*(2*suf[i]+pre[i]-1)*pre[i]/2;
            int x=pre[i]+suf[i]-1;
            int j=qy(i-pre[i],x+1);
            f[i]+=f[j];
            f[i]+=1ll*(i-pre[i]-j)*x;
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans+=1ll*pre[i]*(pre[i]+1)/2;
            int j=qy(i-pre[i],pre[i]+1);
            ans+=f[j];
            ans+=1ll*(i-pre[i]-j)*pre[i];
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    在Myeclipse中移除项目对Hibernate的支持
    使用MyEclipse可视化开发Hibernate实例
    利用MyEclipse自动创建PO类、hbm文件(映射文件)、DAO
    Mtk Camera
    Linux问题,磁盘分区打不开了
    Android SDK在线更新镜像服务器大全
    TeamTalk——ubuntu服务端部署
    Nginx
    VCC/AVCC/VDD/AVDD区别
    android studio and sdk mirror for China
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13843381.html
Copyright © 2011-2022 走看看