zoukankan      html  css  js  c++  java
  • Codeforces 1037F. Maximum Reduction

    总感觉我这种做法会T,一直没写,看了其他人的题解也是这样,,,就果断写了,,可能数据不太深,或者玄学复杂度

    题意即求xk-1长度的所有区间的最大值的和,对每一个i(数组下边),他对答案的贡献数量就是在以ar[i]为最大值的最大子区间中所有符合条件的区间数量

    求ar[i]的作用区间,即,求最小的l,对于x>=l&&x<i,ar[x]<=ar[i];求最大的r,对于k<=r&&k>i,ar[k]<ar[i];则ar[i]的作用区间为[l,r];我代码中的ar[i]的作用区间为(pre[i],nex[i])

    然后遍历i左右中更小的区间,求ar[i]对答案的贡献数量即可,代码思路应该很清晰

    #include<iostream>
    #include<cstdio> 
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<string.h>
    #include<cstring>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<fstream>
    #include<cstdlib>
    #include<ctime>
    #include<list>
    #include<climits>
    #include<bitset>
    using namespace std;
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("input.in", "r", stdin);freopen("output.in", "w", stdout);
    #define left asfdasdasdfasdfsdfasfsdfasfdas1
    #define tan asfdasdasdfasdfasfdfasfsdfasfdas
    typedef long long ll;
    typedef unsigned int un;
    const int desll[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    const ll mod=1e9+7;
    const int maxn=2e6+7;
    const int maxm=1e9+7;
    const double eps=1e-4;
    int m,n,k;
    int ar[maxn];
    int pre[maxn],nex[maxn];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&ar[i]);
        pre[1]=0;
        for(int i=2;i<=n;i++){
            int ins=i-1;
            while(ins>0 && ar[ins]<ar[i])ins=pre[ins];
            pre[i]=ins;
        }
        nex[n]=n+1;
        for(int i=n-1;i>0;i--){
            int ins=i+1;
            while(ins<=n && ar[ins]<=ar[i])ins=nex[ins];
            nex[i]=ins;
        }
        //for(int i=1;i<=n;i++)cout<<pre[i]<<" ";cout<<endl;
        //for(int i=1;i<=n;i++)cout<<nex[i]<<" ";cout<<endl;
        ll ans=0;
        for(int i=1;i<=n;i++){
            int l=pre[i],r=nex[i];
            ll a,b;
            if(i-l<r-i){
                for(int x=l+1;x<=i;x++){//x为符合条件的区间的起始点
                    a=(i-x+1-1+m-2)/(m-1);//a为包含i的区间中最少的(m-1)段数
                    a=max(a,1LL);
                    b=(r-x-1)/(m-1);//b为以r-1为区间终点,可以贡献的最多(m-1)段数
                    ///cout<<"x = "<<x<<" "<<a<<" "<<b<<endl;
                    if(b>=a){
                        ans = (ans + (b-a+1)*ar[i]%mod)%mod;
                    }
                }
            }
            else{
                for(int x=i;x<r;x++){
                    a=(x-i+1-1+m-2)/(m-1);
                    a=max(a,1LL);
                    b=(x-l-1)/(m-1);
                    //cout<<"x = "<<x<<" "<<a<<" "<<b<<endl;
                    if(b>=a){
                        ans = (ans + (b-a+1)*ar[i]%mod)%mod;
                    }
                }
            }
            //cout<<i<<" "<<ans<<" "<<a<<" "<<b<<endl;
        }
        printf("%I64d
    ",ans);
    
    
    
        return 0;
    }
  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/wa007/p/9586054.html
Copyright © 2011-2022 走看看