码迷,mamicode.com
首页 > 其他好文 > 详细

【set】【链表】hdu6058 Kanade's sum

时间:2017-08-02 00:36:34      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:scan   return   排序   第一个   insert   upper   结构   out   依次   

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;
}

【set】【链表】hdu6058 Kanade's sum

标签:scan   return   排序   第一个   insert   upper   结构   out   依次   

原文地址:http://www.cnblogs.com/autsky-jadek/p/7271342.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!