zoukankan      html  css  js  c++  java
  • hdu 6058 Kanade's sum(模拟链表)

    Kanade's sum

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 2723    Accepted Submission(s): 1132

    Problem Description
    Give you an array A[1..n]of length n

    Let f(l,r,k) be the k-th largest element of A[l..r].

    Specially , f(l,r,k)=0 if rl+1<k.

    Give you k , you need to calculate nl=1nr=lf(l,r,k)

    There are T test cases.

    1T10

    kmin(n,80)

    A[1..n] is a permutation of [1..n]

    n5105
     
    Input
    There is only one integer T on first line.

    For each test case,there are only two integers n,k on first line,and the second line consists of n integers which means the array A[1..n]
     
    Output
    For each test case,output an integer, which means the answer.
     
    Sample Input
    1
    5 2
    1 2 3 4 5
     
     
    Sample Output
    30
    Source
     
    Recommend
    liuyiding   |   We have carefully selected several similar problems for you:  6119 6118 6117 6116 6115 
     

    题目大意:给出一个n和一个k,求1~n的每个区间的第k大的总和是多少,区间长度小于k的话,贡献为0.

    题解:一开始先维护一个满的链表,然后从小到大删除,每次算完一个数,就在链表里面删除,算x的时候,保证删除的数都比x小,都可以用来算贡献。i和pre[i]和nxt[i]的距离就是小于当前的数的数目+1。

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    int T,n,k;
    long long ans;
    int pos[1000005],a[1000005];
    int pre[1000005],nxt[1000005];
    long long lnum[1000],rnum[1000];
    
    
    void del(int p)
    {
        pre[nxt[p]]=pre[p];
        nxt[pre[p]]=nxt[p];
    }
    
    int main()
    {
         scanf("%d",&T);
        for(;T>0;T--)
        {
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                pos[a[i]]=i;
            }
    
            for(int i=1;i<=n;i++)
            {
                pre[i]=i-1;
                nxt[i]=i+1;
            }
            ans=0;
    
            for(int i=1;i<=n-k+1;i++) //枚举第 k 大的数是 i 时
            {
               int l=0,r=0;
    
               for(int j=pos[i];j>0 && l<=k;j=pre[j])  // 在i这个数位置的左边,比i大的k个数的位置
                  lnum[++l]=j-pre[j];
    
    
               for(int j=pos[i];j<=n && r<=k;j=nxt[j]) // 在i这个数位置的右边,比i大的k个数的位置
                  rnum[++r]=nxt[j]-j;
    
               for(int j=1;j<=l;j++)
                if (k-j+1<=r && k-j+1>=1)  // 求的是一个区间内,已经满足i为第k大的情况下,能微调的位置种数(lnum[j]-lnum[j+1])*(rnum[k-j+2]-rnum[k-j+1])
                   ans=ans+lnum[j]*rnum[k-j+1]*i;
    
               del(pos[i]); //删除
    
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    不能选中EXCEL单元格直接复制内容到数据库
    trim c# .net
    Postion and AlignmentPoint
    format详解
    range()函数详解
    蓝桥杯,查找整数,python
    蓝桥杯,杨辉三角形,Python
    蓝桥杯,回文数,Python
    微信小程序页面间的数据传递和数据共享
    蓝桥杯,特殊回文数,Python
  • 原文地址:https://www.cnblogs.com/stepping/p/7357565.html
Copyright © 2011-2022 走看看