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;
    }
  • 相关阅读:
    mysql修改数据表名
    HDU 5742 It's All In The Mind (贪心)
    HDU 5752 Sqrt Bo (数论)
    HDU 5753 Permutation Bo (推导 or 打表找规律)
    HDU 5762 Teacher Bo (暴力)
    HDU 5754 Life Winner Bo (博弈)
    CodeForces 455C Civilization (并查集+树的直径)
    CodeForces 455B A Lot of Games (博弈论)
    CodeForces 455A Boredom (DP)
    HDU 4861 Couple doubi (数论 or 打表找规律)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7271342.html
Copyright © 2011-2022 走看看