• 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;
    }
  • 相关阅读:
    052、Java中使用do…while循环实现1~100的累加
    051、Java中使用while循环实现1~100的累加
    050、Java中使用switch判断,使用字符串判断
    一个DOM元素绑定多个事件时,先执行冒泡还是捕获
    cookies,sessionStorage和localStorage的区别
    雅虎网页性能优化的35条黄金守则
    多域名指向同一个网站的好处
    减少页面加载时间的方法
    网站文件和资源的优化
    语义化的html
  • 原文地址:https://www.cnblogs.com/wa007/p/9586054.html
Copyright © 2020-2023  润新知