• HDU


    Bryce1010模板

    http://acm.hdu.edu.cn/showproblem.php?pid=6058

    /*
    思路是:找出每个x为第k大的区间个数有多少
    用pos[i]保存当前x的位置,pre[i]表示向x的左侧扩展k个,next[i]表示向x的右侧扩展k个
    然后计算出在左侧到右侧这个范围有多少个区间数符合条件
    计算出结果后将pre和next后挪以为,接着计算下一个值
    */
    
    #include<bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    const int MAXN=5e5+10;
    ll pos[MAXN+10];
    ll pre[MAXN+10];
    ll nxt[MAXN+10];
    ll l[MAXN+10],r[MAXN+10];
    ll n,k,x;
    
    void del(int x)
    {
        pre[nxt[x]]=pre[x];
        nxt[pre[x]]=nxt[x];
    }
    
    
    
    ll cal(ll x)
    {
        ll cnt=0;
        ll c1=0,c2=0;
    
        for(int i=x;i>0;i=pre[i])
        {
            l[++c1]=i-pre[i];
            if(c1==k)break;
        }
        for(int i=x;i<=n;i=nxt[i])
        {
            r[++c2]=nxt[i]-i;
            if(c2==k)break;
        }
        //计算从左侧区间到右侧区间的区间数
        for(int i=1;i<=c1;i++)
        {
            if(k-i+1<=c2)
                cnt=cnt+l[i]*r[k-i+1];
        }
        return cnt;//返回区间数量
    
    }
    
    
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            //ll n,k,x;
            ll ans=0;
            scanf("%lld%lld",&n,&k);
            for(int i=1;i<=n;i++)
            {
                cin>>x;
                pos[x]=i;
                pre[i]=i-1;
                nxt[i]=i+1;
            }
            pre[0]=0;nxt[n+1]=n+1;
            for(int i=1;i<=n;i++)//计算每个x的区间数
            {
                ll cnt=cal(pos[i]);
    //            cout<<cnt<<endl;
                ans+=cnt*i;
                del(pos[i]);
            }
            cout<<ans<<endl;
        }
    
        return 0;
    }
    
    
    
    
    
    
  • 相关阅读:
    java 键盘监听事件
    DOM扩展
    DOM
    CSS hack
    客户端检测
    BOM
    函数表达式
    面向对象的程序设计
    引用类型(下)
    引用类型(上)
  • 原文地址:https://www.cnblogs.com/bryce1010/p/9386867.html
Copyright © 2020-2023  润新知