zoukankan      html  css  js  c++  java
  • 【set】【链表】hdu6058 Kanade's sum

    f(l,r,K)表示区间l,r里面的K大值,问你所有连续子区间的f之和。

    l(i)表示i左侧第一个比它大的数的位置,r(i)表示i右侧第一个比它大的数的位置。可以用set处理出来。

    把数从大到小排序,依次插入。然后更新l(i),r(i),形成链形结构。

    然后对于一个i,向左跳最多K次,将这些位置记录下来,然后向右跳最多K次,每个右侧的位置最多有一个左侧的位置合法。累计答案。

    #include<cstdio>
    #include<set>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    set<int>S;
    typedef set<int>::iterator ITER;
    ll ans;
    int T,n,K,a[500010],b[500010],L[500010],R[500010];
    int ls[500010],rs[500010];
    bool cmp(const int &i,const int &j){
        return a[i]>a[j];
    }
    int main(){
    //    freopen("1003.in","r",stdin);
    //    freopen("1003.out","w",stdout);
        scanf("%d",&T);
        for(;T;--T){
            S.clear();
            ans=0;
            scanf("%d%d",&n,&K);
            for(int i=1;i<=n;++i){
                scanf("%d",&a[i]);
            }
            for(int i=1;i<=n;++i){
                b[i]=i;
            }
            sort(b+1,b+n+1,cmp);
            for(int i=1;i<=n;++i){
                ITER it=S.lower_bound(b[i]);
                if(i>1 && it!=S.begin()){
                    --it;
                    L[b[i]]=*it;
                    R[*it]=b[i];
                }
                else{
                    L[b[i]]=-1;
                }
                it=S.upper_bound(b[i]);
                if(i>1 && it!=S.end()){
                    R[b[i]]=*it;
                    L[*it]=b[i];
                }
                else{
                    R[b[i]]=-1;
                }
                int e1=0,e2=0;
                ls[0]=rs[0]=b[i];
                for(int j=b[i],l=1;l<=K && L[j]!=-1;j=L[j],++l){
                    ls[++e1]=L[j];
                }
                if(e1<K){
                    ls[++e1]=0;
                }
                for(int l=1,j=b[i];l<=K && R[j]!=-1;j=R[j],++l){
                    rs[++e2]=R[j];
                    if(e2-1+(ls[e1]==0 ? e1-1 : e1)>=K-1){
                        ans+=(ll)(ls[K-e2]-ls[K-e2+1])*(ll)(rs[e2]-rs[e2-1])*(ll)a[b[i]];
                    }
                }
                if(e2<K){
                    rs[++e2]=n+1;
                }
                if(rs[e2]==n+1 && e2-1+((e1==K || ls[e1]==0) ? e1-1 : e1)>=K-1){
                    ans+=(ll)(ls[K-e2]-ls[K-e2+1])*(ll)(rs[e2]-rs[e2-1])*(ll)a[b[i]];
                }
                else if(K==1){
                    ans+=(ll)(b[i]-(L[b[i]]==-1 ? 0 : L[b[i]]))*(ll)((R[b[i]]==-1 ? n+1 : R[b[i]])-b[i])*(ll)a[b[i]];
                }
                S.insert(b[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Centos常用命令之:文件与目录管理
    Centos常用命令之:ls和cd
    Centos6.9连接工具设置
    CentOS6.9安装
    mysql-5.7.18-winx64 免安装版配置
    Struts1开山篇
    参考用bat文件
    QT界面开发-c++ 如何在Qt中将QVariant转换为QString,反之亦然?【转载】
    QT界面开发-QAxObject 解析 excel 时报错error LNK2019: 无法解析的外部符号
    QT界面开发-QAxObject 读写excel(COM组件)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7271342.html
Copyright © 2011-2022 走看看