P2048 [NOI2010] 超级钢琴(贪心 + RMQ

#include 
//using int_max = 0x3f3f3f3f;
#define long_max 9223372036854775807;
using namespace std;
typedef long long ll;
typedef pair PII;
typedef pair PDD;
using VI = vector;
typedef unsigned long long ull;
const int mod = 1e8 - 3;
int n,k,l,r;
int a[5000010];
int s[5000010];
int st[5000010][32];
int id[5000010][32];
struct range{
    int pos,l,r,mp;
    bool operator < (range u)const{
        return s[mp] - s[pos-1] < s[u.mp] - s[u.pos-1];
    }
}tmp;



void init(){
    for(int i=1;i<=n;i++){
        st[i][0] = s[i];
        id[i][0] = i;
    }

    for(int j=1;j<=log2(n)+1;j++){
        for(int i=1;i+(1< st[i+(1<<(j-1))][j-1]){
                st[i][j] = st[i][j-1];
                id[i][j] = id[i][j-1];
            }else{
                st[i][j] = st[i+(1<<(j-1))][j-1];
                id[i][j] = id[i+(1<<(j-1))][j-1];
            }
        }
    }
}
int query(int l, int r){
    int k = log2(r-l+1);
    if(st[l][k] > st[r-(1<>n>>k>>l>>r;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) s[i] = s[i-1] + a[i];
    init();
    priority_queue q;
    for(int i=1;i+l-1<=n;i++){
        tmp.pos = i;
        tmp.l = i+l-1;
        tmp.r = min(n,i+r-1);
        tmp.mp = query(tmp.l,tmp.r);
        //cout< l){
            tmp.pos = pos;
            tmp.l = l;
            tmp.r = mp-1;
            tmp.mp = query(tmp.l,tmp.r);
            q.push(tmp);
        }
        if(mp < r){
            tmp.pos = pos;
            tmp.l = mp+1;
            tmp.r = r;
            tmp.mp = query(tmp.l,tmp.r);
            q.push(tmp);

        }

    }
    cout<

洛谷首个紫,

其实思路并不难,主要是代码实现方面脑子灵光不够

本质上来说就是RMQ问题  

当前端点为 i      选择 i+l-1 i+r-1 中的最大值,位置为k,

然后就考虑选取次大值,其中次大值一定再 i+l-1 , k -1    或者  k + 1 , i+r-1 中

简单点说,就是选择一个最大值,从最大值的位置把区间分开,构成俩个新的待选区间

你可能感兴趣的:(数据结构题,算法,c++,图论)