超级钢琴

NOI2010

暴力30分

为了应对评论区清一色的屑,我特地把这个动图搬过来镇博,看在它的面子上,踩的轻点

 

 

变量解释放代码里了,就是那个maxsite用st维护保存的是最大值的位置,名字起得很贴切来着

思路大体就是暴力匹配,然后匹配到L到R里最大值,然后将L,R以选到的点pos对半分开继续匹配

 

#include <bits/stdc++.h>
#define Re register int 
#define LL long long
#define ki kiritokazuto
//暴力被试过了MLE还有TLE的 
//试一下 
using namespace std;
//这种写法有点小骚 
/*
inline void in(int &x) {
    int f = 0; x = 0; char c = getchar();
    while(c < '0' || c > '9') f |= c == '-', c = getchar();
    while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    x = f ? -x : x;    
}*/
namespace kiritokazuto{ 
        template <typename T> inline void in(T &x) {
            int f = 0; x = 0; char c = getchar();
            while(c < '0' || c > '9') f |= c == '-', c = getchar();
            while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
            x = f ? -x : x;    
        }
        template <typename T> inline void ot(T x) {
            if (x < 0) putchar('-'), x = -x;
            if (x > 9) write(x / 10); putchar(x % 10 + '0');
        }
} 
using namespace kiritokazuto;
 
namespace work{
    #define Re register int 
    #define LL long long
    #define ki kiritokazuto
    static const int maxn = 5e5 + 100000;
    static const int Inf = -2147483647;
    int n, m;
    int L, R;
    int sum[maxn], maxsite[maxn][20];
    LL ans;    
    
    struct Node    {
        int l, r, L, R;//l起点,r终点(即是要选的点),L, R(终点的范围,为了给它劈开)  
        bool operator < (const Node x) const{
            return sum[r] - sum[l] < sum[x.r] - sum[x.l];
        }
    };
    int get_end(int l,int r){//找终点 
        if(r > n) r = n;
        if(l > r) return Inf;//不能劈了 
        if(l == r) return r;
        int k = 1;
        while((1 << k + 1) <= r - l) k++;
        if(sum[maxsite[l][k]] >= sum[maxsite[r - (1 << k) + 1][k]]) return maxsite[l][k];
        return maxsite[r - (1 << k) + 1][k];
    }
    priority_queue <Node> q;
    inline void MAIN() {
        in(n);
        in(m);
        in(L);
        in(R);
        for(Re i = 1, x; i <= n; i++){ 
            in(x);
            sum[i] = sum[i-1] + x;
            maxsite[i][0] = i;
        }
        for(Re j = 1; (1 << j) <= n; j++)
            for(Re i = 1; i + (1 << j) - 1 <= n; i++)
                if(sum[maxsite[i][j-1]] >= sum[maxsite[i + (1 << j - 1)][j - 1]]) maxsite[i][j] = maxsite[i][j - 1];
                else maxsite[i][j] = maxsite[i + (1 << j - 1)][j - 1];
        for(Re i = 1; i + L - 1 <= n; i++)
             q.push((Node){i - 1, get_end(i + L - 1, min(i + R - 1, n)), i + L - 1, min(i + R - 1, n)});
    
        for(Re i = 1; i <= m; i ++){
            int l = q.top().l;
            int r = q.top().r;
            L = q.top().L;
            R = q.top().R;
            q.pop();
            ans += sum[r] - sum[l];
            if(r > L) q.push((Node){l, get_end(L, r - 1), L, r - 1});
            //l........L .....r......R
            //               还能劈开左边 
            if(r < R) q.push((Node){l, get_end(r + 1, R), r + 1, R});
            //l........L......r.......R
            //               还能劈开右边 
            }
        cout << ans; 
        #undef ki
    }
}

signed main() {
    work :: MAIN();
}

 

posted @ 2022-02-14 10:52  kiritokazuto  阅读(105)  评论(5)    收藏  举报