zoukankan      html  css  js  c++  java
  • HDU 6058 Kanade's sum 二分,链表

    Kanade's sum

    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
     

    题解:

      我们只要求出对于一个数x左边最近的k个比他大的和右边最近k个比他大的,扫一下就可以知道有几个区间的k大值是x.

      我们考虑从大到小插入空位,每次维护一个链表,链表里只有>=x的数,那么往左往右找只要暴力跳k次,删除也是O(1)的。

      时间复杂度:O(nk)

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    typedef unsigned long long ULL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 1e6+10, M = 1e3+20,inf = 2e9,mod = 1e9 + 7;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,k,a[N],pos[N],lef[N],righ[N],L[N],R[N];
    set<int > G;
    set<int >:: iterator it,itt;
    void insers(int x,int y) {
        int tmp = L[x];
        L[y] = tmp;
        R[y] = x;
    
        R[tmp] = y;
        L[x] = y;
    }
    int main() {
        int T;
        T = read();
        while(T--) {
            G.clear();
            n = read();
            k = read();
            for(int i = 1; i <= n; ++i) {
                a[i] = read();
                pos[a[i]] = i;
            }
            if(k == 0) {
                puts("0");
                continue;
            }
            G.insert(0);
            G.insert(n+1);
            L[0] = -1;
            R[0] = n+1;
            L[n+1] = 0;
            R[n+1] = -1;
            for(int i = n; i > n - k + 1; --i) {
    
                it = (G.lower_bound(pos[i]));
                insers(*it,pos[i]);
                 G.insert(pos[i]);
            }
    
            LL ans = 0;
            for(int i = n-k+1; i >= 1; --i) {
    
                it = (G.lower_bound(pos[i]));
                int po = *it;
                for(int j = 0; j <= k; ++j) lef[j] = -1;
    
                lef[0] = pos[i];
                for(int j = 1,h = L[po]; j <= k && h != -1; ++j, h = L[h]) {
                    lef[j] = h;
                }
                po = *it;
                righ[0] = pos[i];
                for(int j = 1,h = po; j <= k && h != -1; ++j, h = R[h]) {
                    righ[j] = h;
                    if(lef[k-j+1] != -1)
                        ans += 1LL*i*(lef[k-j] - lef[k - j + 1]) * (righ[j] - righ[j-1]);
                }
                insers(*it,pos[i]);
                G.insert(pos[i]);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Android TextView中的ellipsize属性
    Android 仿微信点赞和评论弹出框
    Java 数组倒序
    Android List去掉重复数据
    Android HttpClient get传递数组
    android HttpClient
    kali中的APT软件包处理工具(apt-get)、Debian软件包管理器(dpkg)、源代码压缩和Nessus安装实用指南
    安装Kali里的应用程序或软件包
    渗透测试方法论
    Kali Linux的介绍
  • 原文地址:https://www.cnblogs.com/zxhl/p/7273375.html
Copyright © 2011-2022 走看看