【白话系列】未完待续

图论当中:

    1、Dijistra+Heap 求最短路

    2、Floyd 求最短路

    3、SPFA 求最短路

    4、Prim 求最小生成树

    5、Kruskal 求最小生成树

    6、Tarjan 求强连通分量

    7、Tarjan 求双连通分量

    8、Tarjan 求桥

    9、Tarjan 求割点

    10、Kosaraju 求强连通分量

    11、Dinic 求最大流

    12、SPFA 求费用流

树论当中:

    1、Tarjan 求最近公共祖先

    2、倍增法 求最近公共祖先

    3、Splay 伸展树

    4、Treap 随机平衡树

    5、树状数组

    6、线段树


// 题目来源: NOI 2010
// 题目大意: 超级钢琴( 详见原题 )
// 解决方法: 区间分离 + ST算法 + 堆
// 代码时间: 2013 4 6

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 500002
using namespace std;

int n, k, L, R, t, cnt, ans;
int c[2*N], l[2*N], r[2*N], p[2*N], b[2*N], v[2*N], heap[2*N], f[N][20];

void up   ( int           );
void down ( int           );
void push ( int, int, int );

int main( )
{
    freopen( "piano.in", "r", stdin );
    freopen( "piano.out", "w", stdout );

    scanf( "%d%d%d%d", &n, &k, &L, &R );
    for( int i = 1; i <= n; i++ )
    {
        scanf( "%d", &c[i] );
        c[i] += c[i-1];
    }
    for( int i = 1; i <= n; i++ )
        f[i][0] = i;
    for( int j = 1; j < 20; j++ )
        for( int i = 0; i <= n; i++ )
        {
            if( i + ( 1 << j ) - 1 > n ) break;
            int temp = i + ( 1 << j-1 );
            f[i][j] = ( c[ f[i][j-1] ] < c[ f[temp][j-1] ] )? f[i][j-1]: f[temp][j-1];
        }
    for( int i = 1; i <= n; i++ )
        push( max( i - R, 0 ), i - L, i );
    for( int i = 1; i < k; i++ )
    {
        int num = heap[1];
        ans += v[num];
        swap( heap[1], heap[cnt] );
        cnt--;
        down( 1 );
        push( l[num], b[num]-1, p[num] );
        push( b[num]+1, r[num], p[num] );
    }
    printf( "%d", ans + v[ heap[1] ] );
    return 0;
}

void up( int i )
{
    int D = i >> 1, data = heap[i];
    while( D && v[data] > v[ heap[D] ] )
    {
        heap[i] = heap[D];
        i = D;
        D = i >> 1;
    }
    heap[i] = data;
}

void down( int i )
{
    int S = i << 1, data = heap[i];
    while( S <= cnt )
    {
        if( S < cnt && v[ heap[S+1] ] > v[ heap[S] ] ) S++;
        if( v[ heap[S] ] < v[ data ] ) break;
        i = S;
        S = i << 1;
    }
    heap[i] = data;
}

void push( int L, int R, int P )
{
    l[++t] = max( L, 0 );
    r[t] = R;
    p[t] = P;
    if( r[t] < 0 || l[t] > r[t] ) return void( --t );
    int lg = int( log( r[t] - l[t] + 1 ) / log( 2 ) ), temp = r[t] - ( 1 << lg ) + 1;
    b[t] = ( c[ f[ l[t] ][lg] ] < c[ f[temp][lg] ] )? f[ l[t] ][lg]: f[temp][lg];
    v[t] = c[ p[t] ] - c[ b[t] ];
    heap[++cnt] = t;
    up( cnt );
}


你可能感兴趣的:(【白话系列】未完待续)