Luogu P2048. [NOI2010] Super Piano

Original link: https://www.shuizilong.com/house/archives/luogu-p2048-noi2010-%E8%B6%85%E7%BA%A7%E9%92%A2%E7%90%B4/

blank.jpg

You can first write a violent RMQ to solve the 10-point code of K=1, to ensure that you have not read the wrong question and understood it as a string problem.

Then top K can use a method similar to the ugly number Humble Numbers in [USACO3.1] to open a pile, and every time a number is found, it will be split and stuffed back.

The amount of data in this question is large enough, the subscript of the query array starts from 0, and the position of rmq is also asked, which is very suitable for us to use our newly learned O(n)-O(1) RMQ to show our talents! . . .

  
   
#include <lastweapon/bitwise>  
   
  
   
using namespace lastweapon;  
   
  
   
const int N = int(5e5) + 9;  
   
int s[N];  
   
int n, K, L, R;  
   
  
   
template<typename T> struct rmq {  
   
	vector<T> v; int n;  
   
	static const int b = 30; // block size  
   
	vector<int> mask, t; // mask and sparse table  
   
  
   
	int op(int x, int y) {  
   
		return v[x] < v[y] ? x : y;  
   
	}  
   
	// least significant set bit  
   
	int lsb(int x) {  
   
		return x & -x;  
   
	}  
   
	// index of the most significant set bit  
   
	int msb_index(int ​​x) {  
   
		return __builtin_clz(1)-__builtin_clz(x);  
   
	}  
   
	// answer query of v[r-size+1..r] using the masks, given size <= b  
   
	int small(int r, int size = b) {  
   
		// get only 'size' least significant bits of the mask  
   
		// and then get the index of the msb of that  
   
		int dist_from_r = msb_index(mask[r] & ((1<<size)-1));  
   
  
   
		return r - dist_from_r;  
   
	}  
   
  
   
	rmq(){}  
   
  
   
	rmq(const vector<T>& v_) : v(v_), n(v. size()), mask(n), t(n) {  
   
		int curr_mask = 0;  
   
		for (int i = 0; i < n; i++) {  
   
  
   
			// shift mask by 1, keeping only the 'b' least significant bits  
   
			curr_mask = (curr_mask<<1) & ((1<<b)-1);  
   
  
   
			while (curr_mask > 0 and op(i, i - msb_index(lsb(curr_mask))) == i) {  
   
				// current value is smaller than the value represented by the  
   
				// last 1 in curr_mask, so we need to turn off that bit  
   
				curr_mask ^= lsb(curr_mask);  
   
			}  
   
			// append extra 1 to the mask  
   
			curr_mask |= 1;  
   
  
   
			mask[i] = curr_mask;  
   
		}  
   
  
   
		// build sparse table over the n/b blocks  
   
		// the sparse table is linearized, so what would be at  
   
		// table[j][i] is stored in table[(n/b)*j + i]  
   
		for (int i = 0; i < n/b; i++) t[i] = small(b*i+b-1);  
   
		for (int j = 1; (1<<j) <= n/b; j++) for (int i = 0; i+(1<<j) <= n/b; i++)  
   
			t[n/b*j+i] = op(t[n/b*(j-1)+i], t[n/b*(j-1)+i+(1<<(j-1) )]);  
   
	}  
   
	// query(l, r) returns the actual minimum of v[l..r]  
   
	// to get the index, just change the first and last lines of the function  
   
	T query(int l, int r) {  
   
		// query too small  
   
		//if (r-l+1 <= b) return v[small(r, r-l+1)];  
   
		if (r-l+1 <= b) return small(r, r-l+1);  
   
  
   
		// get the minimum of the endpoints  
   
		// (there is no problem if the ranges overlap with the sparse table query)  
   
		int ans = op(small(l+b-1), small(r));  
   
  
   
		// 'x' and 'y' are the blocks we need to query over  
   
		int x = l/b+1, y = r/b-1;  
   
  
   
		if (x <= y) {  
   
			int j = msb_index(y-x+1);  
   
			ans = op(ans, op(t[n/b*j+x], t[n/b*j+y-(1<<j)+1]));  
   
		}  
   
  
   
		//return v[ans];  
   
		return ans;  
   
	}  
   
};  
   
  
   
  
   
rmq<int> T;  
   
  
   
struct rec {  
   
    int i, l, r, m, f;  
   
    rec(int i, int l, int r) : i(i), l(l), r(r), m(T. query(l, r)) {  
   
        f = s[i] - s[m];  
   
    }  
   
    bool operator < (const rec& r) const {  
   
        return f < rf;  
   
    }  
   
};  
   
  
   
int main() {  
   
  
   
#ifndef ONLINE_JUDGE  
   
    freopen("in.txt", "r", stdin);  
   
    //freopen("/Users/minakokojima/Documents/GitHub/ACM-Training/Workspace/out.txt", "w", stdout);  
   
#endif  
   
  
   
    RD(n, K, L, R);  
   
  
   
    VI a; a.PB(0);  
   
    REP_1(i, n) RD(s[i]) += s[i-1], a.PB(s[i]); a.pop_back();  
   
  
   
    T = rmq<int>(a);  
   
  
   
    priority_queue<rec> Q;  
   
    FOR_1(i, L, n) {  
   
        Q.push(rec(i, max(0, iR), iL));  
   
    }  
   
  
   
    LL z = 0; DO(K) {  
   
        auto u = Q.top(); Q.pop(); z += uf;  
   
        if (um != ul) Q. push(rec(ui, ul, um-1));  
   
        if (um != ur) Q.push(rec(ui, u.m+1, ur));  
   
    }  
   
  
   
    cout << z << endl;  
   
}  
   
  
   

This article is reproduced from: https://www.shuizilong.com/house/archives/luogu-p2048-noi2010-%E8%B6%85%E7%BA%A7%E9%92%A2%E7%90%B4/
This site is only for collection, and the copyright belongs to the original author.