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\n",ans);
    }
    return 0;
}

 

posted @ 2017-08-02 13:13  meekyan  阅读(286)  评论(0编辑  收藏  举报